UserLevelOrder.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <?php
  2. namespace app\models\user;
  3. use app\admin\model\user\User as UserModel;
  4. use app\admin\model\user\UserBill as UserBillAdmin;
  5. use app\admin\model\user\UserLevel;
  6. use app\admin\model\user\UserTaskFinish;
  7. use app\models\store\StoreBargain;
  8. use app\models\store\StoreCart;
  9. use app\models\store\StoreCombination;
  10. use app\models\store\StoreCouponUser;
  11. use app\models\store\StoreOrderCartInfo;
  12. use app\models\store\StoreOrderStatus;
  13. use app\models\store\StorePink;
  14. use app\models\store\StoreProduct;
  15. use app\models\store\StoreSeckill;
  16. use app\models\system\SystemStore;
  17. use app\models\system\SystemUserLevel;
  18. use app\models\system\SystemUserTask;
  19. use crmeb\basic\BaseModel;
  20. use crmeb\repositories\PaymentRepositories;
  21. use crmeb\repositories\UserRepository;
  22. use crmeb\services\JsonService as Json;
  23. use crmeb\services\UtilService as Util;
  24. use crmeb\traits\ModelTrait;
  25. use think\db\exception\DataNotFoundException;
  26. use think\db\exception\DbException;
  27. use think\db\exception\ModelNotFoundException;
  28. use think\Model;
  29. /**
  30. * TODO 会员等级Model
  31. * Class UserLevel
  32. * @package app\models\user
  33. */
  34. class UserLevelOrder extends BaseModel
  35. {
  36. /**
  37. * 数据表主键
  38. * @var string
  39. */
  40. protected $pk = 'id';
  41. /**
  42. * 模型名称
  43. * @var string
  44. */
  45. protected $name = 'user_level_order';
  46. use ModelTrait;
  47. /**
  48. * 获取用户等级人数
  49. * @param $uids
  50. * @return int
  51. */
  52. public static function setUserLevelOrderCount($uids)
  53. {
  54. $model = new self();
  55. if (is_array($uids)) $model = $model->where('uid', 'in', $uids);
  56. else $model = $model->where('uid', $uids);
  57. return $model->count();
  58. }
  59. /**
  60. * 设置查询初始化条件
  61. * @param string $alias 表别名
  62. * @param null $model 模型实例化对象
  63. * @return UserLevel
  64. */
  65. public static function valiWhere($alias = '', $model = null)
  66. {
  67. $model = is_null($model) ? new self() : $model;
  68. if ($alias) {
  69. $model = $model->alias($alias);
  70. $alias .= '.';
  71. }
  72. return $model->where("{$alias}status", 1)->where("{$alias}is_del", 0);
  73. }
  74. /**
  75. * 设置会员等级
  76. * @param int $uid 用户uid
  77. * @param int $level_id 等级id
  78. * @return UserLevel|bool|Model
  79. * @throws DataNotFoundException
  80. * @throws ModelNotFoundException
  81. * @throws \think\exception\DbException
  82. */
  83. public static function setUserLevel($uid, $level_id)
  84. {
  85. $vipinfo = SystemUserLevel::get($level_id);
  86. if (!$vipinfo) return false;
  87. $userinfo = User::find($uid);
  88. if (!$userinfo) return false;
  89. $add_valid_time = (int)$vipinfo->valid_date * 86400;
  90. $uservipinfo = self::valiWhere()->where('uid', $uid)->where('level_id', $level_id)->find();
  91. //检查是否购买过
  92. if ($uservipinfo) {
  93. $stay = 0;
  94. //剩余时间
  95. if (time() < $uservipinfo->valid_time) $stay = $uservipinfo->valid_time - time();
  96. //如果购买过当前等级的会员过期了.从当前时间开始计算
  97. //过期时效: 剩余时间+当前会员等级时间+当前time
  98. $add_valid_time = $stay + $add_valid_time + time();
  99. $data['is_forever'] = $vipinfo->is_forever;
  100. $data['valid_time'] = $add_valid_time;
  101. User::where('uid', $uid)->update(['level' => $level_id]);
  102. return self::where('uid', $uid)->where('level_id', $level_id)->update($data);
  103. } else {
  104. $data = [
  105. 'is_forever' => $vipinfo->is_forever,
  106. 'status' => 1,
  107. 'is_del' => 0,
  108. 'grade' => $vipinfo->grade,
  109. 'uid' => $uid,
  110. 'add_time' => time(),
  111. 'level_id' => $level_id,
  112. 'discount' => $vipinfo->discount,
  113. ];
  114. if ($data['is_forever'])
  115. $data['valid_time'] = 0;
  116. else
  117. $data['valid_time'] = $add_valid_time + time();
  118. $data['mark'] = '尊敬的用户' . $userinfo['nickname'] . '在' . date('Y-m-d H:i:s', time()) . '成为了' . $vipinfo['name'];
  119. $res = self::create($data);
  120. if (!$res) return false;
  121. User::where('uid', $uid)->update(['level' => $level_id]);
  122. return $res;
  123. }
  124. }
  125. /**
  126. * 获取当前用户会员等级返回当前用户等级id
  127. * @param int $uid 用户uid
  128. * @param int $grade 会员id
  129. * @return bool|mixed
  130. * @throws DataNotFoundException
  131. * @throws ModelNotFoundException
  132. * @throws \think\exception\DbException
  133. */
  134. public static function getUserLevel($uid, $grade = 0)
  135. {
  136. $model = self::valiWhere();
  137. if ($grade) $model = $model->where('grade', '<', $grade);
  138. $level = $model->where('uid', $uid)->order('grade desc')->field('level_id,is_forever,valid_time,id,status,grade')->find();
  139. if (!$level) return false;
  140. if ($level->is_forever) return $level->id;
  141. //会员已经过期
  142. if (time() > $level->valid_time) {
  143. if ($level->status == 1) {
  144. $level->status = 0;
  145. $level->save();
  146. }
  147. return self::getUserLevel($uid, $level->grade);
  148. } else
  149. //会员没有过期
  150. return $level->id;
  151. }
  152. /**
  153. * 获取会员详细信息
  154. * @param $id 会员记录id
  155. * @param string $keyName 字段名
  156. * @return array|mixed|string|Model|null
  157. * @throws DataNotFoundException
  158. * @throws ModelNotFoundException
  159. * @throws \think\exception\DbException
  160. */
  161. public static function getUserLevelInfo($id, $keyName = '')
  162. {
  163. $vipinfo = self::valiWhere('a')->where('a.id', $id)->field('l.id,a.add_time,l.discount,a.level_id,l.name,l.money,l.icon,l.is_pay,l.grade')
  164. ->join('system_user_level l', 'l.id=a.level_id')->find();
  165. if ($keyName) if (isset($vipinfo[$keyName])) return $vipinfo[$keyName]; else return '';
  166. return $vipinfo;
  167. }
  168. /**
  169. * 获取当前用户已成为的vip id
  170. * @param $uid 用户id
  171. * @return array
  172. */
  173. public static function getUserLevelIds($uid)
  174. {
  175. return self::valiWhere()->group('level_id')->where('uid', $uid)->order('grade asc')->column('level_id', 'level_id');
  176. }
  177. /**
  178. * 余额支付
  179. * @param $order_id
  180. * @param $uid
  181. * @param string $formId
  182. * @return bool
  183. * @throws \think\Exception
  184. * @throws DataNotFoundException
  185. * @throws ModelNotFoundException
  186. * @throws \think\exception\DbException
  187. */
  188. public static function yuePay($order_id, $uid, $formId = '')
  189. {
  190. $orderInfo = self::where('uid', $uid)->where('order_id', $order_id)->where('is_del', 0)->find();
  191. if (!$orderInfo) return self::setErrorInfo('订单不存在!');
  192. if ($orderInfo['paid']) return self::setErrorInfo('该订单已支付!');
  193. // if($orderInfo['pay_type'] != 'yue') return self::setErrorInfo('该订单不能使用余额支付!');
  194. $userInfo = User::getUserInfo($uid);
  195. if ($userInfo['now_money'] < $orderInfo['pay_price'])
  196. return self::setErrorInfo(['status' => 'pay_deficiency', 'msg' => '余额不足' . floatval($orderInfo['pay_price'])]);
  197. self::beginTrans();
  198. $res1 = false !== User::bcDec($uid, 'now_money', $orderInfo['pay_price'], 'uid');
  199. $res2 = UserBill::expend('购买会员', $uid, 'now_money', 'pay_level', $orderInfo['pay_price'], $orderInfo['id'], $userInfo['now_money'], '余额支付' . floatval($orderInfo['pay_price']) . '元购买会员');
  200. $res3 = self::paySuccess($order_id, 'yue', $formId);//余额支付成功
  201. try {
  202. PaymentRepositories::yuePayLevel($userInfo, $orderInfo);
  203. } catch (\Exception $e) {
  204. self::rollbackTrans();
  205. return self::setErrorInfo($e->getMessage());
  206. }
  207. $res = $res1 && $res2 && $res3;
  208. self::checkTrans($res);
  209. return $res;
  210. }
  211. /**
  212. * 微信支付 为 0元时
  213. * @param $order_id
  214. * @param $uid
  215. * @param string $formId
  216. * @return bool
  217. * @throws \think\Exception
  218. * @throws DataNotFoundException
  219. * @throws ModelNotFoundException
  220. * @throws \think\exception\DbException
  221. */
  222. public static function jsPayPrice($order_id, $uid, $formId = '')
  223. {
  224. $orderInfo = self::where('uid', $uid)->where('order_id', $order_id)->where('is_del', 0)->find();
  225. if (!$orderInfo) return self::setErrorInfo('订单不存在!');
  226. if ($orderInfo['paid']) return self::setErrorInfo('该订单已支付!');
  227. $userInfo = User::getUserInfo($uid);
  228. self::beginTrans();
  229. $res1 = UserBill::expend('购买会员', $uid, 'now_money', 'pay_level', $orderInfo['pay_price'], $orderInfo['id'], $userInfo['now_money'], '微信支付' . floatval($orderInfo['pay_price']) . '元购买会员');
  230. $res2 = self::paySuccess($order_id, 'weixin', $formId);//微信支付为0时
  231. $res = $res1 && $res2;
  232. self::checkTrans($res);
  233. return $res;
  234. }
  235. /**
  236. * //TODO 支付成功后
  237. * @param $orderId
  238. * @param string $paytype
  239. * @param string $formId
  240. * @return bool
  241. * @throws DataNotFoundException
  242. * @throws DbException
  243. * @throws ModelNotFoundException
  244. */
  245. public static function paySuccess($orderId, $paytype = 'weixin', $formId = '')
  246. {
  247. $order = self::where('order_id', $orderId)->find();
  248. $resPink = true;
  249. $res1 = self::where('order_id', $orderId)->update(['paid' => 1, 'pay_type' => $paytype, 'pay_time' => time(), 'is_del' => 0]);//订单改为支付
  250. // if ($order->combination_id && $res1 && !$order->refund_status) $resPink = StorePink::createPink($order);//创建拼团
  251. $oid = self::where('order_id', $orderId)->value('id');
  252. // StoreOrderStatus::status($oid, 'pay_success', '用户付款成功');
  253. $now_money = User::where('uid', $order['uid'])->value('now_money');
  254. UserBill::expend('购买会员', $order['uid'], 'now_money', 'pay_money', $order['pay_price'], $order['id'], $now_money, '支付' . floatval($order['pay_price']) . '元购买会员');
  255. //支付成功后
  256. // event('OrderPaySuccess', [$order, $formId]);
  257. self::save_give_level($order['uid'], $order['level_id']);
  258. // 邀请返利
  259. self::rebates($order['uid'], $order['level_id'],$order['id']);
  260. self::give_integral($order['uid'], $order['level_id'],$order['id']);
  261. $res = $res1;
  262. // $res = $res1 && $resPink && UserSpread::setSpreadSure($order['uid']) && User::backOrderBrokerage($order);
  263. return false !== $res;
  264. }
  265. /*
  266. * 购买获得会员等级
  267. * @paran int $uid
  268. * @return json
  269. * */
  270. public static function save_give_level($uid = 0,$level_id = 0)
  271. {
  272. if (!$uid) return Json::fail('缺少参数');
  273. //查询当前选择的会员等级
  274. $systemLevel = \app\admin\model\system\SystemUserLevel::where(['is_show' => 1, 'is_del' => 0, 'id' => $level_id])->find();
  275. if (!$systemLevel) return Json::fail('您选择赠送的会员等级不存在!');
  276. //检查是否拥有此会员等级
  277. $level = UserLevel::where(['uid' => $uid, 'level_id' => $level_id, 'is_del' => 0])->field('valid_time,is_forever')->find();
  278. // if ($level) if (!$level['is_forever'] && time() < $level['valid_time']) return Json::fail('此用户已有该会员等级,无法再次赠送');
  279. //设置会员过期时间
  280. $add_valid_time = (int)$systemLevel->valid_date * 86400;
  281. UserModel::commitTrans();
  282. try {
  283. //保存会员信息
  284. $res = UserLevel::create([
  285. 'is_forever' => $systemLevel->is_forever,
  286. 'status' => 1,
  287. 'is_del' => 0,
  288. 'grade' => $systemLevel->grade,
  289. 'uid' => $uid,
  290. 'add_time' => time(),
  291. 'level_id' => $level_id,
  292. 'discount' => $systemLevel->discount,
  293. 'valid_time' => $systemLevel->discount ? $add_valid_time + time() : 0,
  294. 'mark' => '尊敬的用户【' . UserModel::where('uid', $uid)->value('nickname') . '】在' . date('Y-m-d H:i:s', time()) . '购买会员等级成为' . $systemLevel['name'] . '会员',
  295. ]);
  296. //提取等级任务并记录完成情况
  297. $levelIds = [$level_id];
  298. $lowGradeLevelIds = SystemUserLevel::where('grade', '<', $systemLevel->grade)->where(['is_show' => 1, 'is_del' => 0])->column('id', 'id');
  299. if (count($lowGradeLevelIds)) $levelIds = array_merge($levelIds, $lowGradeLevelIds);
  300. $taskIds = \app\admin\model\system\SystemUserTask::where('level_id', 'in', $levelIds)->column('id', 'id');
  301. $inserValue = [];
  302. foreach ($taskIds as $id) {
  303. $inserValue[] = ['uid' => $uid, 'task_id' => $id, 'status' => 1, 'add_time' => time()];
  304. }
  305. $res = $res && UserModel::where('uid', $uid)->update(['level' => $level_id]);
  306. if ($inserValue) $res && UserTaskFinish::insertAll($inserValue);
  307. $user = UserModel::where('uid', $uid)->find();
  308. // if ($systemLevel['integral']>0) {//赠送积分
  309. //
  310. //
  311. // }
  312. if ($res) {
  313. UserModel::commitTrans();
  314. return Json::successful('购买成功');
  315. } else {
  316. UserModel::rollbackTrans();
  317. return Json::successful('购买失败');
  318. }
  319. } catch (\Exception $e) {
  320. UserModel::rollbackTrans();
  321. return Json::fail('购买失败');
  322. }
  323. }
  324. // 邀请返利
  325. public static function rebates($uid, $level_id,$order_id){
  326. // $spread_id = User::where('uid', $uid)->value('spread_id');
  327. $userInfo = User::getUserInfo($uid);
  328. $spread_Info = User::getUserInfo($userInfo['spread_uid']);
  329. $level_info=SystemUserLevel::where('id', $level_id)->find();
  330. if ($level_info['rebate']>0){
  331. $brokerage = bcmul($level_info['rebate'], $level_info['money'], 2);
  332. $balance = bcadd($spread_Info['integral'], $brokerage, 2);
  333. $mark = '下级用户'.$userInfo['nickname'] . '成为'.$level_info['name'].',奖励推广积分' . floatval($brokerage);
  334. $res1 = UserBill::income('获得推广积分', $userInfo['spread_uid'], 'integral', 'level_integral', $brokerage, $order_id, $balance, $mark);
  335. $res2 = self::bcInc($userInfo['spread_uid'], 'integral', $brokerage, 'uid');
  336. }
  337. return true;
  338. }
  339. // 积分赠送
  340. public static function give_integral($uid, $level_id,$order_id){
  341. // $spread_id = User::where('uid', $uid)->value('spread_id');
  342. $userInfo = User::getUserInfo($uid);
  343. // $spread_Info = User::getUserInfo($userInfo['spread_uid']);
  344. $level_info=SystemUserLevel::where('id', $level_id)->find();
  345. if ($level_info['integral']>0){
  346. $brokerage = bcadd($level_info['integral'], $level_info['money'], 2);
  347. $balance = bcadd($userInfo['integral'], $brokerage, 2);
  348. $mark = '用户'.$userInfo['nickname'] . '成为'.$level_info['name'].',奖励积分' . floatval($brokerage);
  349. $res1 = UserBill::income('获得推广积分', $userInfo['spread_uid'], 'integral', 'level_integral', $brokerage, $order_id, $balance, $mark);
  350. $res2 = self::bcInc($uid, 'integral', $brokerage, 'uid');
  351. }
  352. return true;
  353. }
  354. /**
  355. * 生成订单唯一id
  356. * @param $uid 用户uid
  357. * @return string
  358. */
  359. public static function getNewOrderId()
  360. {
  361. do {
  362. list($msec, $sec) = explode(' ', microtime());
  363. $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
  364. $orderId = 'hy' . $msectime . mt_rand(10000, 99999);
  365. } while (self::be(['order_id' => $orderId]));// $orderId = 'wx' . $msectime . mt_rand(10000, 99999);
  366. return $orderId;
  367. }
  368. // 创建会员订单
  369. public static function CreateOrder($uid, $level_id,$recharge_type)
  370. {
  371. self::beginTrans();
  372. try {
  373. // `grade` int(10) unsigned zerofill NOT NULL COMMENT '会员等级',
  374. // `price` decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '充值金额',
  375. // `give_price` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '购买赠送金额',
  376. // `recharge_type` varchar(32) NOT NULL COMMENT '充值类型',
  377. // `paid` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否支付0未支付1已支付',
  378. // `pay_time` timestamp NULL DEFAULT NULL COMMENT '充值支付时间',
  379. // `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '充值时间',
  380. // `refund_price` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '退款金额',
  381. $levelInfo = SystemUserLevel::get($level_id);
  382. if ($levelInfo['is_spread']==1){ //限定邀请
  383. $userSpread = \app\admin\model\user\User::where('uid', $uid)->value('spread_id');
  384. if ($userSpread<=0){
  385. return self::setErrorInfo('只有受邀请用户才能购买该等级的会员', true);
  386. }
  387. }
  388. $orderInfo = [
  389. 'uid' => $uid,
  390. 'order_id' => self::getNewOrderId(),
  391. 'level_id' =>$level_id,
  392. 'grade' => $levelInfo['grade'],
  393. 'give_price' => $levelInfo['give_price'],
  394. ];
  395. $order = self::create($orderInfo);
  396. if (!$order) return self::setErrorInfo('订单生成失败!', true);
  397. self::commitTrans();
  398. // StoreOrderStatus::status($order['id'], 'cache_key_create_order', '订单生成');
  399. return $order;
  400. } catch (\PDOException $e) {
  401. self::rollbackTrans();
  402. return self::setErrorInfo('生成订单时SQL执行错误错误原因:' . $e->getMessage());
  403. } catch (\Exception $e) {
  404. self::rollbackTrans();
  405. return self::setErrorInfo('生成订单时系统错误错误原因:' . $e->getMessage());
  406. }
  407. }
  408. }