StorePink.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\wap\model\store;
  12. use app\index\controller\PushJob;
  13. use app\wap\model\special\Special;
  14. use app\wap\model\special\SpecialBuy;
  15. use app\wap\model\user\User;
  16. use app\wap\model\user\WechatUser;
  17. use basic\ModelBasic;
  18. use service\WechatTemplateService;
  19. use think\Url;
  20. use traits\ModelTrait;
  21. /**
  22. * 拼团Model
  23. * Class StorePink
  24. * @package app\wap\model\store
  25. */
  26. class StorePink extends ModelBasic
  27. {
  28. use ModelTrait;
  29. public static function getPinkIngCount($k_id)
  30. {
  31. return self::where('a')->where('k_id', $k_id)->count() + 1;
  32. }
  33. public static function getPinkStatusIng($pinkId)
  34. {
  35. return self::where('id', $pinkId)->value('status') == 1 ? false : true;
  36. }
  37. /**
  38. * 助力拼团
  39. * @param int $painId 拼团id
  40. * @return boolen
  41. * */
  42. public static function helpePink($pinId, $nickname, $avatar)
  43. {
  44. $pink = self::where('id', $pinId)->find();
  45. if (!$pink) return self::setErrorInfo('拼团信息暂未查到');
  46. if ($pink->status != 1) return self::setErrorInfo('拼团暂时无法助力');
  47. self::beginTrans();
  48. try {
  49. //获取参团人和团长和拼团总人数
  50. list($pinkAll, $pinkT, $count) = self::getPinkMemberAndPinkK($pink);
  51. //拼团是否完成
  52. if (!$count || $count < 0) return self::setErrorInfo('拼团已完成无法助力');
  53. //拼团超时
  54. if ($pinkT['stop_time'] < time()) return self::setErrorInfo('拼团超时无法助力');
  55. $data = [
  56. 'uid' => 0,
  57. 'type' => 1,
  58. 'order_id' => '',
  59. 'order_id_key' => 0,
  60. 'total_num' => 1,
  61. 'total_price' => $pinkT['total_price'],
  62. 'cid' => $pinkT['cid'],
  63. 'pid' => $pinkT['pid'],
  64. 'price' => $pinkT['price'],
  65. 'add_time' => time(),
  66. 'stop_time' => $pinkT['stop_time'],
  67. 'k_id' => $pinkT['id'],
  68. 'is_tpl' => 0,
  69. 'is_refund' => 0,
  70. 'is_false' => 1,
  71. 'status' => 1,
  72. ];
  73. $pink_false = self::set($data);
  74. if (!$pink_false) return self::setErrorInfo('写入助力拼团失败', true);
  75. $res = self::getDb('store_pink_false')->insert(['pink_id' => $pink_false['id'], 'nickname' => $nickname, 'avatar' => $avatar, 'add_time' => time()]);
  76. if (!$res) return self::setErrorInfo('写入助力拼团虚拟用户失败', true);
  77. //助力拼团加1人判断是否拼团完成;
  78. if (!($count - 1)) {
  79. $idAll = [];
  80. $uidAll = [];
  81. foreach ($pinkAll as $k => $v) {
  82. $idAll[$k] = $v['id'];
  83. if ($v['uid']) $uidAll[$k] = $v['uid'];
  84. }
  85. $idAll[] = $pinkT['id'];
  86. $uidAll[] = $pinkT['uid'];
  87. if (self::setPinkStatus($idAll)) {
  88. $orderAll = self::where('id', 'in', $idAll)->column('order_id');
  89. if (count($orderAll)) StoreOrder::PinkRake($orderAll);//拼团完成反佣金
  90. self::setPinkStopTime($idAll);
  91. if (self::isTpl($uidAll, $pinkT['id'])) self::orderPinkAfter($uidAll, $pinkT['id']);
  92. }
  93. }
  94. self::commitTrans();
  95. return true;
  96. } catch (\Exception $e) {
  97. self::rollbackTrans();
  98. return self::setErrorInfo($e->getMessage());
  99. }
  100. }
  101. /**
  102. * 获取参团人和团长和拼团总人数
  103. * @param array $pink
  104. * @return array
  105. * */
  106. public static function getPinkMemberAndPinkK($pink)
  107. {
  108. //查找拼团团员和团长
  109. if ($pink['k_id']) {
  110. $pinkAll = self::getPinkMember($pink['k_id']);
  111. $pinkT = self::getPinkUserOne($pink['k_id']);
  112. } else {
  113. $pinkAll = self::getPinkMember($pink['id']);
  114. $pinkT = $pink;
  115. }
  116. //获取虚拟拼团团员
  117. $pinkAll = self::getPinkTFalseList($pinkAll, $pinkT['id'], $pinkT['cid']);
  118. $count = count($pinkAll) + 1;
  119. $count = (int)$pinkT['people'] - $count;
  120. $idAll = [];
  121. $uidAll = [];
  122. //收集拼团用户id和拼团id
  123. foreach ($pinkAll as $k => $v) {
  124. $idAll[$k] = $v['id'];
  125. $uidAll[$k] = $v['uid'];
  126. }
  127. $idAll[] = $pinkT['id'];
  128. $uidAll[] = $pinkT['uid'];
  129. return [$pinkAll, $pinkT, $count, $idAll, $uidAll];
  130. }
  131. /**
  132. * 获取某个团的虚拟拼团人物和团
  133. * @param array 团员
  134. * @param int $pinkTId 团长id
  135. * @param int $cid 专题id
  136. * @return array
  137. * */
  138. public static function getPinkTFalseList($pinkAll, $pinkTId, $cid)
  139. {
  140. if (!is_array($pinkAll)) $pinkAll = [];
  141. $falseList = self::where(['a.order_id' => '', 'a.cid' => $cid, 'a.k_id' => $pinkTId, 'a.is_false' => 1, 'a.is_refund' => 0])
  142. ->alias('a')->join('__STORE_PINK_FALSE__ f', 'a.id=f.pink_id')->field(['a.*', 'f.nickname', 'f.avatar'])->select();
  143. $falseList = count($falseList) ? $falseList->toArray() : [];
  144. return array_merge($pinkAll, $falseList);
  145. }
  146. /**
  147. * 拼团完成更改数据写入内容
  148. * @param array $uidAll 当前拼团uid
  149. * @param array $idAll 当前拼团pink_id
  150. * @param array $pinkT 团长信息
  151. * @return int
  152. * */
  153. public static function PinkComplete($uidAll, $idAll, $uid, $pinkT)
  154. {
  155. $pinkBool = 6;
  156. if (self::setPinkStatus($idAll)) {
  157. self::setPinkStopTime($idAll);
  158. $orderAll = self::where('id', 'in', $idAll)->column('order_id');
  159. if (count($orderAll)) StoreOrder::PinkRake($orderAll);//拼团完成反佣金
  160. if (in_array($uid, $uidAll)) {
  161. if (self::isTpl($uidAll, $pinkT['id'])) self::orderPinkAfter($uidAll, $pinkT['id']);
  162. $pinkBool = 1;
  163. } else $pinkBool = 3;
  164. }
  165. return $pinkBool;
  166. }
  167. /**
  168. * 拼团失败 退款
  169. * @param array $pinkAll 拼团数据,不包括团长
  170. * @param array $pinkT 团长数据
  171. * @param int $count 差几人 0为拼团成功
  172. * @param int $pinkBool
  173. * @param array $uidAll 用户uid避免虚拟用户头像重复
  174. * @param boolen $isRunErr 是否返回错误信息
  175. * @param boolen $isIds 是否返回记录所有拼团id
  176. * @return int| boolen
  177. * */
  178. public static function PinkFail($uid, $idAll, $pinkAll, $pinkT, $count, $pinkBool, $uidAll, $isRunErr = false, $isIds = false, $fakeUrl = '/public/system/images/fake.png')
  179. {
  180. self::startTrans();
  181. $pinkIds = [];
  182. try {
  183. if ($pinkT['stop_time'] < time()) {//拼团时间超时 退款
  184. $special = Special::PreWhere()->where(['id' => $pinkT['cid']])->find();
  185. //检查专题是否有虚拟成团
  186. if ($special && $special->is_fake_pink && $special->fake_pink_number && $count) {
  187. // fake_pink_number/100 =补齐比例 $pinkT['people']*补齐比例=补齐人数 人数小数点全部舍去
  188. $fake = bcdiv($special->fake_pink_number, 100, 2);
  189. $num = bcmul($pinkT['people'], $fake, 0);
  190. if ($num > $count) $num = $count;
  191. if (($count - (int)$num) <= 0) {
  192. //获取虚拟用户头像
  193. $userAvatar = User::where('status', 1)->where('uid', 'not in', $uidAll)->limit(0, $num)->column('avatar');
  194. if (count($userAvatar) < $num) {
  195. $usercount = $num - count($userAvatar);
  196. for ($i = 0; $i < $usercount; $i++) {
  197. array_push($userAvatar, $fakeUrl);
  198. }
  199. }
  200. //写入虚拟拼团
  201. foreach ($userAvatar as $item) {
  202. $data = [
  203. 'uid' => 0,
  204. 'type' => 1,
  205. 'order_id' => '',
  206. 'order_id_key' => 0,
  207. 'total_num' => 1,
  208. 'total_price' => $pinkT['total_price'],
  209. 'cid' => $pinkT['cid'],
  210. 'pid' => $pinkT['pid'],
  211. 'price' => $pinkT['price'],
  212. 'add_time' => time(),
  213. 'stop_time' => $pinkT['stop_time'],
  214. 'k_id' => $pinkT['id'],
  215. 'is_tpl' => 0,
  216. 'is_refund' => 0,
  217. 'is_false' => 1,
  218. 'status' => 1,
  219. ];
  220. $pink_false = self::set($data);
  221. if (!$pink_false) return self::setErrorInfo('写入助力拼团失败', true);
  222. $res = self::getDb('store_pink_false')->insert(['pink_id' => $pink_false['id'], 'nickname' => '虚拟用户', 'avatar' => $item, 'add_time' => time()]);
  223. if (!$res) return self::setErrorInfo('写入助力拼团虚拟用户失败', true);
  224. }
  225. //拼团完成处理
  226. $pinkBool = self::PinkComplete($uidAll, $idAll, $uid, $pinkT);
  227. if ($pinkBool === false) return false;
  228. self::commit();
  229. return $pinkBool;
  230. }
  231. }
  232. //团员退款
  233. foreach ($pinkAll as $v) {
  234. if (StoreOrder::orderApplyRefund(StoreOrder::getPinkOrderId($v['order_id_key']), $v['uid'], '拼团时间超时') && self::isTpl($v['uid'], $pinkT['id'])) {
  235. self::orderPinkAfterNo($v['uid'], $v['k_id']);
  236. if ($isIds) array_push($pinkIds, $v['id']);
  237. $pinkBool = 2;
  238. } else {
  239. if ($isRunErr) return self::setErrorInfo(StoreOrder::getErrorInfo(), true);
  240. }
  241. }
  242. //团长退款
  243. if (StoreOrder::orderApplyRefund(StoreOrder::getPinkOrderId($pinkT['order_id_key']), $pinkT['uid'], '拼团时间超时') && self::isTpl($pinkT['uid'], $pinkT['id'])) {
  244. self::orderPinkAfterNo($pinkT['uid'], $pinkT['id']);
  245. if ($isIds) array_push($pinkIds, $pinkT['id']);
  246. $pinkBool = 2;
  247. } else {
  248. if ($isRunErr) return self::setErrorInfo(StoreOrder::getErrorInfo(), true);
  249. }
  250. if (!$pinkBool) $pinkBool = 3;
  251. }
  252. self::commit();
  253. if ($isIds) return $pinkIds;
  254. return $pinkBool;
  255. } catch (\Exception $e) {
  256. self::rollback();
  257. return self::setErrorInfo($e->getMessage());
  258. }
  259. }
  260. /**
  261. * 拼团下架
  262. * @param int $painId 拼团id
  263. * @return boolen
  264. * */
  265. public static function downPink($pinId)
  266. {
  267. $pink = self::where('id', $pinId)->find();
  268. if (!$pink) return self::setErrorInfo('拼团信息暂未查到');
  269. if ($pink->status != 1) return self::setErrorInfo('拼团暂时无法下架');
  270. self::beginTrans();
  271. try {
  272. //获取参团人和团长和拼团总人数
  273. list($pinkAll, $pinkT, $count, $idAll, $uidAll) = StorePink::getPinkMemberAndPinkK($pink);
  274. if (!$count) return self::setErrorInfo('拼团已完成无法下架');
  275. //拼团失败处理退款
  276. $pinkIds = self::PinkFail($pink['uid'], $idAll, $pinkAll, $pinkT, $count, 1, [], true, true);
  277. if ($pinkIds === false) return false;
  278. //更新当前拼团过期时间为当前
  279. self::where('id', 'in', $pinkIds)->update(['stop_time' => time()]);
  280. self::commitTrans();
  281. return true;
  282. } catch (\Exception $e) {
  283. return self::setErrorInfo($e->getMessage(), true);
  284. }
  285. }
  286. /**
  287. * 获取一条拼团数据
  288. * @param $id
  289. * @return mixed
  290. */
  291. public static function getPinkUserOne($id)
  292. {
  293. $model = new self();
  294. $model = $model->alias('p');
  295. $model = $model->field('p.*,u.nickname,u.avatar');
  296. $model = $model->where('id', $id);
  297. $model = $model->join('__USER__ u', 'u.uid = p.uid');
  298. $list = $model->find();
  299. if ($list) return $list->toArray();
  300. else return [];
  301. }
  302. /**
  303. * 获取拼团的团员
  304. * @param $id
  305. * @return mixed
  306. */
  307. public static function getPinkMember($id, $retrn_array = false)
  308. {
  309. $model = new self();
  310. $model = $model->alias('p');
  311. $model = $model->field('p.*,u.nickname,u.avatar');
  312. $model = $model->where('p.k_id', $id);
  313. $model = $model->where('p.is_refund', 0);
  314. $model = $model->join('__USER__ u', 'u.uid = p.uid');
  315. $model = $model->order('p.id asc');
  316. if ($retrn_array) return $model->count();
  317. $list = $model->select();
  318. if ($list) return $list->toArray();
  319. else return [];
  320. }
  321. /**
  322. * 设置结束时间
  323. * @param $idAll
  324. * @return $this
  325. */
  326. public static function setPinkStopTime($idAll)
  327. {
  328. $model = new self();
  329. $model = $model->where('id', 'IN', $idAll);
  330. self::setSpecialBuy($idAll);
  331. return $model->update(['stop_time' => time(), 'status' => 2]);
  332. }
  333. public static function setSpecialBuy($idAll)
  334. {
  335. $allOrderId = self::where('id', 'in', $idAll)->column('order_id');
  336. foreach ($allOrderId as $order_id) {
  337. if ($order = StoreOrder::where(['order_id' => $order_id, 'paid' => 1])->find()) {
  338. SpecialBuy::setAllBuySpecial($order->order_id, $order->uid, $order->cart_id, 1);
  339. }
  340. }
  341. }
  342. /**
  343. * 获取正在拼团的数据 团长
  344. * @return mixed
  345. */
  346. public static function getPinkAll($cid, $pinkId = 0, $limit = 0)
  347. {
  348. $model = new self();
  349. $model = $model->alias('p');
  350. $model = $model->field('p.*,u.nickname,u.avatar');
  351. $model = $model->where('p.stop_time', 'GT', time());
  352. $model = $model->where('p.cid', $cid);
  353. $model = $model->where('p.k_id', 0);
  354. $model = $model->where('p.is_refund', 0);
  355. $model = $model->where('p.status', 1);
  356. $model = $model->order('p.add_time desc');
  357. $model = $model->join('__USER__ u', 'u.uid = p.uid');
  358. if ($limit) $model = $model->limit($limit);
  359. if ($pinkId) $model = $model->where('p.id', 'neq', $pinkId);
  360. $list = $model->select();
  361. if ($list) return $list->toArray();
  362. else return [];
  363. }
  364. public static function setPinkIng($pink, $uid)
  365. {
  366. list($pinkAll, $pinkT, $count, $idAll, $uidAll) = StorePink::getPinkMemberAndPinkK($pink);
  367. if ($pinkT['status'] != 2) {
  368. if (!$count) {//组团完成
  369. self::PinkComplete($uidAll, $idAll, $uid, $pinkT);
  370. } else {
  371. //组团时间到退款
  372. self::PinkFail($uid, $idAll, $pinkAll, $pinkT, $count, 0, $uidAll);
  373. }
  374. }
  375. }
  376. /**
  377. * 参加拼团的人 商品id
  378. * @return mixed
  379. */
  380. public static function getPinkAttend($cid, $type = 1)
  381. {
  382. $model = new self();
  383. $model = $model->alias('p');
  384. $model = $model->field('u.avatar');
  385. $model = $model->where(['p.cid' => $cid, 'p.type' => $type, 'p.is_refund' => 0]);
  386. $model = $model->order('p.add_time desc');
  387. $model = $model->join('__USER__ u', 'u.uid = p.uid');
  388. $list = $model->distinct(true)->select();
  389. if ($list) return $list->toArray();
  390. else return [];
  391. }
  392. public static function getPinkAttendFalse($cid, $type = 1, $limit = 20)
  393. {
  394. $userList = self::where(['a.cid' => $cid, 'a.type' => $type, 'a.is_refund' => 0])
  395. ->distinct(true)->order('a.add_time desc')->alias('a')
  396. ->join('__STORE_PINK_FALSE__ s', 's.pink_id=a.id')
  397. ->field('s.avatar')->limit($limit)->select();
  398. return count($userList) ? $userList->toArray() : [];
  399. }
  400. /**
  401. * 获取还差几人
  402. */
  403. public static function getPinkPeople($kid, $people)
  404. {
  405. $model = new self();
  406. $model = $model->where('k_id', $kid)->where('is_refund', 0);
  407. $count = bcadd($model->count(), 1, 0);
  408. return bcsub($people, $count, 0);
  409. }
  410. /**
  411. * 判断订单是否在当前的拼团中
  412. * @param $orderId
  413. * @param $kid
  414. * @return bool
  415. */
  416. public static function getOrderIdAndPink($orderId, $kid)
  417. {
  418. $model = new self();
  419. $pink = $model->where('k_id', $kid)->whereOr('id', $kid)->column('order_id');
  420. if (in_array($orderId, $pink)) return true;
  421. else return false;
  422. }
  423. /**
  424. * 判断用户是否在团内
  425. * @param $id
  426. * @return int|string
  427. */
  428. public static function getIsPinkUid($id)
  429. {
  430. $uid = User::getActiveUid();
  431. $pinkT = self::where('id', $id)->where('uid', $uid)->where('is_refund', 0)->count();
  432. $pink = self::whereOr('k_id', $id)->where('uid', $uid)->where('is_refund', 0)->count();
  433. if ($pinkT) return true;
  434. if ($pink) return true;
  435. else return false;
  436. }
  437. /**
  438. * 判断是否发送模板消息 0 未发送 1已发送
  439. * @param $uidAll
  440. * @return int|string
  441. */
  442. public static function isTpl($uidAll, $pid)
  443. {
  444. if (is_array($uidAll)) {
  445. $countK = self::where('uid', 'IN', implode(',', $uidAll))->where('is_tpl', 0)->where('id', $pid)->count();
  446. $count = self::where('uid', 'IN', implode(',', $uidAll))->where('is_tpl', 0)->where('k_id', $pid)->count();
  447. } else {
  448. $countK = self::where('uid', $uidAll)->where('is_tpl', 0)->where('id', $pid)->count();
  449. $count = self::where('uid', $uidAll)->where('is_tpl', 0)->where('k_id', $pid)->count();
  450. }
  451. return bcadd($countK, $count, 0);
  452. }
  453. /**
  454. * 拼团成功提示模板消息
  455. * @param $uidAll
  456. * @param $pid
  457. */
  458. public static function orderPinkAfter($uidAll, $pid)
  459. {
  460. foreach ($uidAll as $v) {
  461. try {
  462. if ($openid = WechatUser::uidToOpenid($v)) {
  463. $cart_id = self::alias('p')->where('p.id', $pid)->whereOr('p.k_id', $pid)->where('p.uid', $v)->join('__STORE_ORDER__ a', 'a.order_id=p.order_id')->value('a.cart_id');
  464. WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_SUCCESS, [
  465. 'first' => '亲,您的拼团已经完成了',
  466. 'keyword1' => self::where('id', $pid)->whereOr('k_id', $pid)->where('uid', $v)->value('order_id'),
  467. 'keyword2' => Special::PreWhere()->where('id', $cart_id)->value('title'),
  468. 'remark' => '点击查看订单详情'
  469. ], Url::build('wap/special/order_pink', ['pink_id' => $pid], true, true));
  470. }
  471. } catch (\Exception $e) {
  472. break;
  473. }
  474. }
  475. self::where('uid', 'IN', implode(',', $uidAll))->where('id', $pid)->whereOr('k_id', $pid)->update(['is_tpl' => 1]);
  476. }
  477. /**
  478. * 拼团失败发送的模板消息
  479. * @param $uid
  480. * @param $pid
  481. */
  482. public static function orderPinkAfterNo($uid, $pid)
  483. {
  484. $openid = WechatUser::uidToOpenid($uid);
  485. WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_LOSE, [
  486. 'first' => '亲,您的拼团失败',
  487. 'keyword1' => self::alias('p')->where('p.id', $pid)->whereOr('p.k_id', $pid)->where('p.uid', $uid)->join('__SPECIAL__ c', 'c.id=p.cid')->value('c.title'),
  488. 'keyword2' => self::where('id', $pid)->whereOr('k_id', $pid)->where('uid', $uid)->value('price'),
  489. 'keyword3' => self::alias('p')->where('p.id', $pid)->whereOr('p.k_id', $pid)->where('p.uid', $uid)->join('__STORE_ORDER__ c', 'c.order_id=p.order_id')->value('c.pay_price'),
  490. 'remark' => '点击查看订单详情'
  491. ], Url::build('My/order_pink', ['pink_id' => $pid], true, true));
  492. self::where('id', $pid)->update(['status' => 3]);
  493. self::where('k_id', $pid)->update(['status' => 3]);
  494. }
  495. /**
  496. * 获取当前拼团数据返回订单编号
  497. * @param $id
  498. * @return array|false|\PDOStatement|string|\think\Model
  499. */
  500. public static function getCurrentPink($id)
  501. {
  502. $uid = User::getActiveUid();//获取当前登录人的uid
  503. $pink = self::where('id', $id)->where('uid', $uid)->find();
  504. if (!$pink) $pink = self::where('k_id', $id)->where('uid', $uid)->find();
  505. return StoreOrder::where('id', $pink['order_id_key'])->value('order_id');
  506. }
  507. /**
  508. * 设置where条件
  509. * @param $where
  510. * @param string $alias
  511. * @return $this|StorePink
  512. */
  513. public static function setWhere($where, $alias = '')
  514. {
  515. self::setPinkStop((int)$where['page']);
  516. $model = new self;
  517. if ($alias) {
  518. $model = $model->alias($alias);
  519. $alias .= '.';
  520. }
  521. if ($where['data'] !== '~' && !empty($where['data'])) {
  522. list($startTime, $endTime) = explode('~', $where['data']);
  523. $model = $model->where($alias . 'add_time', '>', strtotime($startTime));
  524. $model = $model->where($alias . 'add_time', '<', strtotime($endTime));
  525. }
  526. if ($where['status']) $model = $model->where($alias . 'status', $where['status']);
  527. if ($where['cid']) $model = $model->where($alias . 'cid', $where['cid']);
  528. if ($where['nickname']) $model = $model->where($alias . 'order_id|' . $alias . 'order_id_key|' . $alias . 'uid', 'LIKE', "%$where[nickname]%");
  529. $model = $model->where($alias . 'k_id', 0);
  530. return $model;
  531. }
  532. /**
  533. * @param $where
  534. * @return array
  535. * @throws \think\Exception
  536. */
  537. public static function getPinkList($where)
  538. {
  539. $data = self::setWhere($where, 'a')->field(['a.*', 'u.nickname'])->join('__USER__ u', 'u.uid=a.uid', 'LEFT')->order('a.id desc')
  540. ->page((int)$where['page'], (int)$where['limit'])->select();
  541. foreach ($data as &$item) {
  542. if ($item['status'] == 1 && $item['stop_time'] < time()) {
  543. $pinkall = self::where(['k_id' => $item['id']])->column('id');
  544. array_push($pinkall, $item['id']);
  545. if (!($item['people'] - count($pinkall))) {
  546. self::where('id', 'in', $pinkall)->update(['status' => 2]);
  547. $item['status'] = 2;
  548. } else {
  549. self::where('id', 'in', $pinkall)->update(['status' => 3]);
  550. $item['status'] = 3;
  551. }
  552. }
  553. if(!$item['nickname']) $item['nickname']='用户被删除';
  554. $item['count_people'] = bcadd(self::where('k_id', $item['id'])->count(), 1, 0);
  555. $item['title'] = Special::where('id', $item['cid'])->value('title');
  556. $item['add_time'] = date('Y-m-d H:i', $item['add_time']);
  557. $item['stop_time'] = date('Y-m-d H:i', $item['stop_time']);
  558. $item['people_true'] = self::where(['k_id' => $item['id'], 'is_false' => 0])->count() + 1;
  559. }
  560. $count = self::setWhere($where)->count();
  561. return compact('data', 'count');
  562. }
  563. /**
  564. * 处理拼团结束
  565. * @param int $page
  566. */
  567. public static function setPinkStop($page = 1)
  568. {
  569. $list = self::where(['k_id' => 0, 'status' => 1])->where('stop_time', '<', time())->page($page, 10)->select();
  570. foreach ($list as $item) {
  571. //获取参团人和团长和拼团总人数
  572. list($pinkAll, $pinkT, $count, $idAll) = StorePink::getPinkMemberAndPinkK($item);
  573. //拼团失败处理退款
  574. self::PinkFail($item['uid'], $idAll, $pinkAll, $pinkT, $count, 1, [], true, true);
  575. }
  576. }
  577. public static function systemPage($where)
  578. {
  579. $model = new self;
  580. $model = $model->alias('p');
  581. $model = $model->field('p.*');
  582. if ($where['data'] !== '') {
  583. list($startTime, $endTime) = explode(' - ', $where['data']);
  584. $model = $model->where('add_time', '>', strtotime($startTime));
  585. $model = $model->where('add_time', '<', strtotime($endTime));
  586. }
  587. if ($where['status']) $model = $model->where('status', $where['status']);
  588. $model = $model->where('k_id', 0);
  589. $model = $model->order('id desc');
  590. return self::page($model, function ($item) use ($where) {
  591. $item['count_people'] = bcadd(self::where('k_id', $item['id'])->count(), 1, 0);
  592. $item['title'] = Special::where('id', $item['cid'])->value('title');
  593. }, $where);
  594. }
  595. public static function isPinkBe($data, $id)
  596. {
  597. $data['id'] = $id;
  598. $count = self::where($data)->count();
  599. if ($count) return $count;
  600. $data['k_id'] = $id;
  601. $count = self::where($data)->count();
  602. if ($count) return $count;
  603. else return 0;
  604. }
  605. public static function isPinkStatus($pinkId)
  606. {
  607. if (!$pinkId) return false;
  608. $stopTime = self::where('id', $pinkId)->value('stop_time');
  609. if ($stopTime < time()) return true; //拼团结束
  610. else return false;//拼团未结束
  611. }
  612. /**
  613. * 判断拼团结束 后的状态
  614. * @param $pinkId
  615. * @return bool
  616. */
  617. public static function isSetPinkOver($pinkId)
  618. {
  619. $people = self::where('id', $pinkId)->value('people');
  620. $stopTime = self::where('id', $pinkId)->value('stop_time');
  621. if ($stopTime < time()) {
  622. $countNum = self::getPinkPeople($pinkId, $people);
  623. if ($countNum) return false;//拼团失败
  624. else return true;//拼团成功
  625. } else return true;
  626. }
  627. /**
  628. * 拼团退款
  629. * @param $id
  630. * @return bool
  631. */
  632. public static function setRefundPink($oid)
  633. {
  634. $res = true;
  635. $order = StoreOrder::where('id', $oid)->find();
  636. if ($order['pink_id']) $id = $order['pink_id'];
  637. else return $res;
  638. $count = self::where('id', $id)->where('uid', $order['uid'])->find();//正在拼团 团长
  639. $countY = self::where('k_id', $id)->where('uid', $order['uid'])->find();//正在拼团 团员
  640. if (!$count && !$countY) return $res;
  641. if ($count) {//团长
  642. //判断团内是否还有其他人 如果有 团长为第二个进团的人
  643. $kCount = self::where('k_id', $id)->order('add_time asc')->find();
  644. if ($kCount) {
  645. $res11 = self::where('k_id', $id)->update(['k_id' => $kCount['id']]);
  646. $res12 = self::where('id', $kCount['id'])->update(['stop_time' => $count['add_time'] + 86400, 'k_id' => 0]);
  647. $res1 = $res11 && $res12;
  648. $res2 = self::where('id', $id)->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $kCount['id'], 'status' => 3]);
  649. } else {
  650. $res1 = true;
  651. $res2 = self::where('id', $id)->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
  652. }
  653. //修改结束时间为前一秒 团长ID为0
  654. $res = $res1 && $res2;
  655. } else if ($countY) {//团员
  656. $res = self::where('id', $countY['id'])->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
  657. }
  658. return $res;
  659. }
  660. /**
  661. * 拼团人数完成时,判断全部人都是未退款状态
  662. * @param $pinkIds
  663. * @return bool
  664. */
  665. public static function setPinkStatus($pinkIds)
  666. {
  667. $orderPink = self::where('id', 'IN', $pinkIds)->where('is_refund', 1)->count();
  668. if (!$orderPink) return true;
  669. else return false;
  670. }
  671. /**
  672. * 创建拼团
  673. * @param $order
  674. * @return mixed
  675. */
  676. public static function createPink($order)
  677. {
  678. $order = StoreOrder::tidyOrder($order, true)->toArray();
  679. //开团的用户走else
  680. if ($order['pink_id']) {//拼团存在
  681. $res = false;
  682. $pink['uid'] = $order['uid'];//用户id
  683. if (self::isPinkBe($pink, $order['pink_id'])) return false;
  684. $pink['type'] = 1;
  685. $pink['order_id'] = $order['order_id'];//订单id 生成
  686. $pink['order_id_key'] = $order['id'];//订单id 数据库id
  687. $pink['total_num'] = $order['total_num'];//购买个数
  688. $pink['total_price'] = $order['pay_price'];//总金额
  689. $pink['k_id'] = $order['pink_id'];//拼团id
  690. $special = Special::PreWhere()->where('id', $order['cart_id'])->find();
  691. if (!$special) return false;
  692. $pink['cid'] = $order['combination_id'];//拼团产品id
  693. $pink['pid'] = $order['cart_id'];//产品id
  694. $pink['people'] = $special['pink_number'];//几人拼团
  695. $pink['price'] = $special['is_fake_pink'] ? $special['pink_money'] : $special['money'];//单价
  696. $pink['stop_time'] = 0;//结束时间
  697. $pink['add_time'] = time();//开团时间
  698. $res = $res1 = self::set($pink)->toArray();
  699. $openid = WechatUser::uidToOpenid($order['uid']) ? WechatUser::uidToOpenid($order['uid']) : "";
  700. if ($openid) {
  701. WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_SUCCESS, [
  702. 'first' => '恭喜您拼团成功,点击查看拼团详情~',
  703. 'keyword1' => $order['order_id'],
  704. 'keyword2' => self::alias('p')->where('p.id', $res1['id'])->where('p.uid', $res1['uid'])->join('__SPECIAL__ c', 'c.id=p.cid')->value('c.title'),
  705. 'remark' => '分享至朋友圈或好友群,成团速度更快哦~'
  706. ], Url::build('wap/special/order_pink', ['pink_id' => $res1['id']], true, true));
  707. }
  708. if ($people = self::getPinkPeople($order['pink_id'], $special['pink_number'])) {
  709. $userInfo = User::where('uid', $order['uid'])->find();
  710. if (!$userInfo->is_promoter && $userInfo->spread_uid) {
  711. $spreadOpenid = WechatUser::uidToOpenid($userInfo->spread_uid);
  712. WechatTemplateService::sendTemplate($spreadOpenid, WechatTemplateService::PINK_ORDER_REMIND, [
  713. 'first' => '您的好友【' . $userInfo->nickname . '】通过您的邀请开始了【' . $special['title'] . '】的拼团!',
  714. 'keyword1' => $special['title'],
  715. 'keyword2' => '差' . $people . '人',
  716. 'remark' => '点我立即协助【' . $userInfo->nickname . '】拼团,拼团成功即可获得佣金!'
  717. ], Url::build('wap/special/order_pink', ['pink_id' => $res1['id'], 'is_help' => 1], true, true));
  718. }
  719. }
  720. //处理拼团完成
  721. list($pinkAll, $pinkT, $count, $idAll, $uidAll) = self::getPinkMemberAndPinkK($pink);
  722. if ($pinkT['status'] == 1) {
  723. if (!$count || $count < 0)//组团完成
  724. self::PinkComplete($uidAll, $idAll, $pink['uid'], $pinkT);
  725. else
  726. self::PinkFail($pink['uid'], $idAll, $pinkAll, $pinkT, $count, 0, $uidAll);
  727. } else if ($pinkT['status'] == 2) {
  728. SpecialBuy::setAllBuySpecial($order['order_id'], $order['uid'], $order['cart_id'], 1);
  729. self::where('id', $res1['id'])->update(['is_tpl' => 1, 'stop_time' => time(), 'status' => 2]);
  730. }
  731. if ($res) return true;
  732. else return false;
  733. } else {
  734. $res = false;
  735. $pink['type'] = 1;
  736. $pink['uid'] = $order['uid'];//用户id
  737. $pink['order_id'] = $order['order_id'];//订单id 生成
  738. $pink['order_id_key'] = $order['id'];//订单id 数据库id
  739. $pink['total_num'] = $order['total_num'];//购买个数
  740. $pink['total_price'] = $order['pay_price'];//总金额
  741. $pink['k_id'] = 0;//拼团id
  742. $pink['cid'] = $order['combination_id'];//拼团产品id
  743. $pink['pid'] = $order['cart_id'];//产品id
  744. $special = Special::PreWhere()->where('id', $order['cart_id'])->find();
  745. if (!$special) return false;
  746. $pink['people'] = $special['pink_number'];//几人拼团
  747. $pink['price'] = $special['is_fake_pink'] ? $special['pink_money'] : $special['money'];//单价
  748. $pink['stop_time'] = bcadd(time(), bcmul($order['pink_time'], 3600, 0), 0);//结束时间
  749. $pink['add_time'] = time();//开团时间
  750. $res1 = self::set($pink)->toArray();
  751. $do_job_pink['pink_id'] = $res1['id'];
  752. $do_job_pink['pink_time'] = bcmul($order['pink_time'],3600,0);
  753. $res2 = StoreOrder::where('id', $order['id'])->update(['pink_id' => $res1['id']]);
  754. $res = $res1 && $res2;
  755. $openid = WechatUser::uidToOpenid($order['uid']);
  756. WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_PINGT_SUCCESS, [
  757. 'first' => '您已成功开团,点击查看拼团详情~',
  758. 'keyword1' => $special['title'],
  759. 'keyword2' => $special['pink_money'],
  760. 'keyword3' => $special['pink_number'],
  761. 'keyword4' => date('Y-m-d H:i:s', $pink['add_time']),
  762. 'remark' => '分享至朋友圈或好友群,成团速度更快哦~'
  763. ], Url::build('wap/special/order_pink', ['pink_id' => $res1['id']], true, true));
  764. $userInfo = User::where('uid', $order['uid'])->find();
  765. try {
  766. if ($userInfo && !$userInfo->is_promoter && $userInfo->spread_uid) {
  767. $spreadOpenid = WechatUser::uidToOpenid($userInfo->spread_uid);
  768. $people = self::getPinkPeople($res1['id'], $special['pink_number']);
  769. WechatTemplateService::sendTemplate($spreadOpenid, WechatTemplateService::PINK_ORDER_REMIND, [
  770. 'first' => '您的好友【' . $userInfo->nickname . '】通过您的邀请开始了【' . $special['title'] . '】的拼团!',
  771. 'keyword1' => $special['title'],
  772. 'keyword2' => '差' . $people . '人',
  773. 'remark' => '点我立即协助【' . $userInfo->nickname . '】拼团,拼团成功即可获得佣金!'
  774. ], Url::build('wap/special/order_pink', ['pink_id' => $res1['id'], 'is_help' => 1], true, true));
  775. }
  776. } catch (\Exception $e) {
  777. }
  778. PushJob::actionWithDoPinkJob($do_job_pink);
  779. if ($res) return true;
  780. else return false;
  781. }
  782. }
  783. }