StorePink.php 40 KB

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