StorePink.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. <?php
  2. /**
  3. *
  4. * @author: xaboy<365615158@qq.com>
  5. * @day: 2017/12/18
  6. */
  7. namespace app\models\store;
  8. use app\models\routine\RoutineFormId;
  9. use app\models\routine\RoutineTemplate;
  10. use app\models\user\User;
  11. use app\models\user\WechatUser;
  12. use app\models\wechat\WechatTemplate;
  13. use crmeb\basic\BaseModel;
  14. use crmeb\services\WechatTemplateService;
  15. use crmeb\traits\ModelTrait;
  16. use PDOStatement;
  17. use think\db\exception\DataNotFoundException;
  18. use think\db\exception\DbException;
  19. use think\db\exception\ModelNotFoundException;
  20. use think\facade\Log;
  21. use think\facade\Route;
  22. /**
  23. * TODO 拼团Model
  24. * Class StorePink
  25. * @package app\models\store
  26. */
  27. class StorePink extends BaseModel
  28. {
  29. /**
  30. * 数据表主键
  31. * @var string
  32. */
  33. protected $pk = 'id';
  34. /**
  35. * 模型名称
  36. * @var string
  37. */
  38. protected $name = 'store_pink';
  39. use ModelTrait;
  40. public static function merSet($mer_id, $alias = '')
  41. {
  42. return $mer_id ? self::where($alias ? $alias . '.mer_id' : 'mer_id', $mer_id) : new self;
  43. }
  44. /*
  45. * 获取拼团完成的用户
  46. * @param int $uid 用户id
  47. * @return array
  48. * */
  49. public static function getPinkOkList($uid)
  50. {
  51. $list = self::alias('a')->where('a.status', 2)->where('a.is_refund', 0)->where('a.uid', '<>', $uid)->join('User u', 'u.uid=a.uid', 'right')->column('nickname', 'id');
  52. $msg = [];
  53. foreach ($list as &$item) {
  54. $msg[] = $item .= '拼团成功';
  55. }
  56. return $msg;
  57. }
  58. /*
  59. * 获取拼团完成的商品总件数
  60. * */
  61. public static function getPinkOkSumTotalNum($id)
  62. {
  63. return self::where('status', 2)->where('is_refund', 0)->sum('total_num');
  64. }
  65. /**
  66. * 获取一条拼团数据
  67. * @param $id
  68. * @param bool $mer_id
  69. * @return mixed
  70. */
  71. public static function getPinkUserOne($id, $mer_id = false)
  72. {
  73. $model = self::merSet($mer_id, 'p');
  74. $model = $model->alias('p');
  75. $model = $model->field('p.*,u.nickname,u.avatar');
  76. $model = $model->where('id', $id);
  77. $model = $model->join('user u', 'u.uid = p.uid');
  78. return $model->find();
  79. }
  80. /**
  81. * 获取拼团的团员
  82. * @param $id
  83. * @return mixed
  84. */
  85. public static function getPinkMember($id)
  86. {
  87. $model = new self();
  88. $model = $model->alias('p');
  89. $model = $model->field('p.*,u.nickname,u.avatar');
  90. $model = $model->where('k_id', $id);
  91. $model = $model->where('is_refund', 0);
  92. $model = $model->join('user u', 'u.uid = p.uid');
  93. $model = $model->order('id asc');
  94. return $model->select();
  95. }
  96. /**
  97. * 设置结束时间
  98. * @param $idAll
  99. * @return $this
  100. */
  101. public static function setPinkStopTime($idAll)
  102. {
  103. $model = new self();
  104. $model = $model->where('id', 'IN', $idAll);
  105. return $model->update(['stop_time' => time(), 'status' => 2]);
  106. }
  107. /**
  108. * 获取正在拼团的数据 团长
  109. * @param int $cid 商品id
  110. * @param int $isAll 是否查找所有拼团
  111. * @return array
  112. */
  113. public static function getPinkAll($cid, $isAll = false)
  114. {
  115. $model = new self();
  116. $model = $model->alias('p');
  117. $model = $model->field('p.id,p.uid,p.people,p.price,p.stop_time,u.nickname,u.avatar');
  118. $model = $model->where('stop_time', '>', time());
  119. $model = $model->where('p.cid', $cid);
  120. $model = $model->where('p.k_id', 0);
  121. $model = $model->where('p.is_refund', 0);
  122. $model = $model->order('p.add_time desc');
  123. $model = $model->join('user u', 'u.uid = p.uid');
  124. $list = $model->select();
  125. $list = count($list) ? $list->toArray() : [];
  126. if ($isAll) {
  127. $pindAll = [];
  128. foreach ($list as &$v) {
  129. $v['count'] = self::getPinkPeople($v['id'], $v['people']);
  130. $v['h'] = date('H', $v['stop_time']);
  131. $v['i'] = date('i', $v['stop_time']);
  132. $v['s'] = date('s', $v['stop_time']);
  133. $pindAll[] = $v['id'];//开团团长ID
  134. $v['stop_time'] = (int)$v['stop_time'];
  135. }
  136. return [$list, $pindAll];
  137. }
  138. return $list;
  139. }
  140. /**
  141. * 获取还差几人
  142. */
  143. public static function getPinkPeople($kid, $people)
  144. {
  145. $model = new self();
  146. $model = $model->where('k_id', $kid)->where('is_refund', 0);
  147. $count = bcadd($model->count(), 1, 0);
  148. return bcsub($people, $count, 0);
  149. }
  150. /**
  151. * 判断订单是否在当前的拼团中
  152. * @param $orderId
  153. * @param $kid
  154. * @return bool
  155. */
  156. public static function getOrderIdAndPink($orderId, $kid)
  157. {
  158. $model = new self();
  159. $pink = $model->where('k_id|id', $kid)->column('order_id');
  160. if (in_array($orderId, $pink)) return true;
  161. else return false;
  162. }
  163. /**
  164. * 判断用户是否在团内
  165. * @param $id
  166. * @return int|string
  167. */
  168. public static function getIsPinkUid($id = 0, $uid = 0)
  169. {
  170. $pink = self::where('k_id|id', $id)->where('uid', $uid)->where('is_refund', 0)->count();
  171. if ($pink) return true;
  172. else return false;
  173. }
  174. /**
  175. * 判断是否发送模板消息 0 未发送 1已发送
  176. * @param $uidAll
  177. * @return int|string
  178. */
  179. public static function isTpl($uidAll, $pid)
  180. {
  181. if (is_array($uidAll))
  182. $count = self::where('uid', 'IN', implode(',', $uidAll))->where('is_tpl', 0)->where('id|k_id', $pid)->count();
  183. else
  184. $count = self::where('uid', $uidAll)->where('is_tpl', 0)->where('k_id|id', $pid)->count();
  185. return $count;
  186. }
  187. /**
  188. * 拼团成功提示模板消息
  189. * @param $uidAll
  190. * @param $pid
  191. */
  192. public static function orderPinkAfter($uidAll, $pid)
  193. {
  194. $pinkInfo = self::where('p.id|p.k_id', $pid)->alias('p')->field(['p.people', 't.title', 'p.add_time', 'p.order_id', 'u.nickname'])->join('user u', 'u.uid = p.uid')->join('store_combination t', 'p.cid = t.id')->find();
  195. if (!$pinkInfo) return false;
  196. foreach ($uidAll as $key => &$item) {
  197. $openid = WechatUser::uidToOpenid($item, 'openid');
  198. $routineOpenid = WechatUser::uidToOpenid($item, 'routine_openid');
  199. $nickname = WechatUser::uidToOpenid(self::where('id', $pid)->value('uid'), 'nickname');
  200. if ($openid) { //公众号模板消息
  201. // $firstWeChat = '亲,您的拼团已经完成了';
  202. $keyword1WeChat = self::where('id|k_id', $pid)->where('uid', $item)->value('order_id');
  203. $keyword2WeChat = self::alias('p')->where('p.id|p.k_id', $pid)->where('p.uid', $item)->join('store_combination c', 'c.id=p.cid')->value('c.title');
  204. // $remarkWeChat = '点击查看订单详情';
  205. // $urlWeChat = Route::buildUrl('order/detail/' . $keyword1WeChat)->suffix('')->domain(true)->build();
  206. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_SUCCESS, [
  207. // 'first' => $firstWeChat,
  208. // 'keyword1' => $keyword1WeChat,
  209. // 'keyword2' => $keyword2WeChat,
  210. // 'remark' => $remarkWeChat
  211. // ], $urlWeChat);
  212. $wechatTemplate = new WechatTemplate();
  213. $wechatTemplate->sendOrderPinkSuccess($item, $keyword1WeChat, $keyword2WeChat, $pid);
  214. } else if ($routineOpenid) {// 小程序模板消息
  215. RoutineTemplate::sendPinkSuccess($item, $pinkInfo['title'], $pinkInfo['nickname'] ?? '', $pinkInfo['add_time'], $pinkInfo['people'], '/pages/order_details/index?order_id=' . $pinkInfo['order_id']);
  216. }
  217. }
  218. self::beginTrans();
  219. $res1 = self::where('uid', 'IN', implode(',', $uidAll))->where('id|k_id', $pid)->update(['is_tpl' => 1]);
  220. self::checkTrans($res1);
  221. }
  222. /**
  223. * 拼团失败发送的模板消息
  224. * @param $uid
  225. * @param $pid
  226. */
  227. public static function orderPinkAfterNo($uid, $pid, $fillTilt = '', $isRemove = false)
  228. {
  229. $store = self::alias('p')->where('p.id|p.k_id', $pid)->field('c.*')->where('p.uid', $uid)->join('store_combination c', 'c.id=p.cid')->find();
  230. $pink = self::where('id|k_id', $pid)->where('uid', $uid)->find();
  231. $openid = WechatUser::uidToOpenid($uid, 'openid');
  232. $routineOpenid = WechatUser::uidToOpenid($uid, 'routine_openid');
  233. $wechatTemplate = new WechatTemplate();
  234. if ($isRemove) {
  235. if ($openid) {//公众号发送模板消息
  236. // $urlWeChat = Route::buildUrl('order/detail/' . $pink->order_id)->suffix('')->domain(true)->build();
  237. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_LOSE, [
  238. // 'first' => '亲,您的拼团取消',
  239. // 'keyword1' => $store->title,
  240. // 'keyword2' => $pink->price,
  241. // 'keyword3' => $pink->price,
  242. // 'remark' => '点击查看订单详情'
  243. // ], $urlWeChat);
  244. $wechatTemplate->sendOrderPinkClone($uid, $pink, $store->title);
  245. } else if ($routineOpenid) {//小程序发送模板消息
  246. RoutineTemplate::sendPinkFail($uid, $store->title, $pink->people, '亲,您的拼团取消,点击查看订单详情', '/pages/order_details/index?order_id=' . $pink->order_id);
  247. }
  248. } else {
  249. if ($openid) {//公众号发送模板消息
  250. // $urlWeChat = Route::buildUrl('order/detail/' . $pink->order_id)->suffix('')->domain(true)->build();
  251. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_LOSE, [
  252. // 'first' => '亲,您的拼团失败',
  253. // 'keyword1' => $store->title,
  254. // 'keyword2' => $pink->price,
  255. // 'keyword3' => $pink->price,
  256. // 'remark' => '点击查看订单详情'
  257. // ], $urlWeChat);
  258. $wechatTemplate->sendOrderPinkFial($uid, $pink, $store->title);
  259. } else if ($routineOpenid) {//小程序发送模板消息
  260. RoutineTemplate::sendPinkFail(
  261. $uid,
  262. $store->title,
  263. $pink->people,
  264. '亲,您拼团失败,自动为您申请退款,退款金额为:' . $pink->price,
  265. '/pages/order_details/index?order_id=' . $pink->order_id
  266. );
  267. }
  268. }
  269. self::where('id', $pid)->update(['status' => 3, 'stop_time' => time()]);
  270. self::where('k_id', $pid)->update(['status' => 3, 'stop_time' => time()]);
  271. }
  272. /**
  273. * 获取当前拼团数据返回订单编号
  274. * @param $id
  275. * @param $uid
  276. * @return array|false|PDOStatement|string|\think\Model
  277. * @throws DataNotFoundException
  278. * @throws DbException
  279. * @throws ModelNotFoundException
  280. */
  281. public static function getCurrentPink($id, $uid)
  282. {
  283. $pink = self::where('id', $id)->where('uid', $uid)->find();
  284. if (!$pink) $pink = self::where('k_id', $id)->where('uid', $uid)->find();
  285. return StoreOrder::where('id', $pink['order_id_key'])->value('order_id');
  286. }
  287. public static function systemPage($where)
  288. {
  289. $model = new self;
  290. $model = $model->alias('p');
  291. $model = $model->field('p.*,c.title,u.nickname,u.avatar');
  292. $model = self::getModelTime($where, $model, "p.add_time");
  293. if ($where['status']) $model = $model->where('p.status', $where['status']);
  294. $model = $model->where('p.mer_id', $where['mer_id']);
  295. $model = $model->where('p.k_id', 0);
  296. $model = $model->order('p.id desc');
  297. $model = $model->join('StoreCombination c', 'c.id=p.cid');
  298. $model = $model->join('user u', 'u.uid = p.uid');
  299. $count = $model->count();
  300. $list = $model->page((int)$where['page'], (int)$where['limit'])
  301. ->select()
  302. ->each(function ($item) {
  303. $item['count_people'] = bcadd(self::where('k_id', $item['id'])->count(), 1, 0);
  304. });
  305. return compact('count', 'list');
  306. }
  307. public static function isPinkBe($data, $id)
  308. {
  309. $data['id'] = $id;
  310. $count = self::where($data)->count();
  311. if ($count) return $count;
  312. $data['k_id'] = $id;
  313. $count = self::where($data)->count();
  314. if ($count) return $count;
  315. else return 0;
  316. }
  317. public static function isPinkStatus($pinkId)
  318. {
  319. if (!$pinkId) return false;
  320. $stopTime = self::where('id', $pinkId)->value('stop_time');
  321. if ($stopTime < time()) return true; //拼团结束
  322. else return false;//拼团未结束
  323. }
  324. /**
  325. * 判断拼团结束 后的状态
  326. * @param $pinkId
  327. * @return bool
  328. */
  329. public static function isSetPinkOver($pinkId)
  330. {
  331. $people = self::where('id', $pinkId)->value('people');
  332. $stopTime = self::where('id', $pinkId)->value('stop_time');
  333. if ($stopTime < time()) {
  334. $countNum = self::getPinkPeople($pinkId, $people);
  335. if ($countNum) return false;//拼团失败
  336. else return true;//拼团成功
  337. } else return true;
  338. }
  339. /**
  340. * 拼团退款
  341. * @param $id
  342. * @return bool
  343. */
  344. public static function setRefundPink($oid)
  345. {
  346. $res = true;
  347. $order = StoreOrder::where('id', $oid)->find();
  348. if ($order['pink_id']) $id = $order['pink_id'];
  349. else return $res;
  350. $count = self::where('id', $id)->where('uid', $order['uid'])->find();//正在拼团 团长
  351. $countY = self::where('k_id', $id)->where('uid', $order['uid'])->find();//正在拼团 团员
  352. if (!$count && !$countY) return $res;
  353. if ($count) {//团长
  354. //判断团内是否还有其他人 如果有 团长为第二个进团的人
  355. $kCount = self::where('k_id', $id)->order('add_time asc')->find();
  356. if ($kCount) {
  357. $res11 = self::where('k_id', $id)->update(['k_id' => $kCount['id']]);
  358. $res12 = self::where('id', $kCount['id'])->update(['stop_time' => $count['add_time'] + 86400, 'k_id' => 0]);
  359. $res1 = $res11 && $res12;
  360. $res2 = self::where('id', $id)->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $kCount['id'], 'status' => 3]);
  361. } else {
  362. $res1 = true;
  363. $res2 = self::where('id', $id)->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
  364. }
  365. //修改结束时间为前一秒 团长ID为0
  366. $res = $res1 && $res2;
  367. } else if ($countY) {//团员
  368. $res = self::where('id', $countY['id'])->update(['stop_time' => time() - 1, 'k_id' => 0, 'is_refund' => $id, 'status' => 3]);
  369. }
  370. return $res;
  371. }
  372. /**
  373. * 拼团人数完成时,判断全部人都是未退款状态
  374. * @param $pinkIds
  375. * @return bool
  376. */
  377. public static function setPinkStatus($pinkIds)
  378. {
  379. $orderPink = self::where('id', 'IN', $pinkIds)->where('is_refund', 1)->count();
  380. if (!$orderPink) return true;
  381. else return false;
  382. }
  383. /**
  384. * 创建拼团
  385. * @param $order
  386. * @return mixed
  387. * @throws DataNotFoundException
  388. * @throws DbException
  389. * @throws ModelNotFoundException
  390. */
  391. public static function createPink($order)
  392. {
  393. $order = StoreOrder::tidyOrder($order, true, false, $order['mer_id'])->toArray();
  394. $openid = WechatUser::uidToOpenid($order['uid'], 'openid');
  395. $routineOpenid = WechatUser::uidToOpenid($order['uid'], 'routine_openid');
  396. $product = StoreCombination::where('id', $order['combination_id'])->field('effective_time,title')->find();
  397. if ($product) {
  398. if ($order['pink_id']) {//拼团存在
  399. $res = false;
  400. $pink['uid'] = $order['uid'];//用户id
  401. if (self::isPinkBe($pink, $order['pink_id'])) return false;
  402. $pink['order_id'] = $order['order_id'];//订单id 生成
  403. $pink['order_id_key'] = $order['id'];//订单id 数据库id
  404. $pink['total_num'] = $order['total_num'];//购买个数
  405. $pink['total_price'] = $order['pay_price'];//总金额
  406. $pink['k_id'] = $order['pink_id'];//拼团id
  407. foreach ($order['cartInfo'] as $v) {
  408. $pink['cid'] = $v['combination_id'];//拼团商品id
  409. $pink['pid'] = $v['product_id'];//商品id
  410. $pink['people'] = StoreCombination::where('id', $v['combination_id'])->value('people');//几人拼团
  411. $pink['price'] = $v['productInfo']['price'];//单价
  412. $pink['stop_time'] = 0;//结束时间
  413. $pink['add_time'] = time();//开团时间
  414. $pink['mer_id'] = $order['mer_id'];//所属商户
  415. $res = self::create($pink)->toArray();
  416. }
  417. if ($openid) { //公众号模板消息
  418. // $urlWeChat = Route::buildUrl('order/detail/' . $order['order_id'])->suffix('')->domain(true)->build();
  419. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_SUCCESS, [
  420. // 'first' => '亲,您已成功参与拼团',
  421. // 'keyword1' => $order['order_id'],
  422. // 'keyword2' => $product->title,
  423. // 'remark' => '点击查看订单详情'
  424. // ], $urlWeChat);
  425. $wechatTemplate = new WechatTemplate();
  426. $wechatTemplate->sendOrderPinkUseSuccess($order['uid'], $order['order_id'], $product->title, $order['pink_id']);
  427. } else if ($routineOpenid) {
  428. $nickname = User::where('uid', self::where('id', $pink['k_id'])->value('uid'))->value('nickname');
  429. RoutineTemplate::sendPinkSuccess(
  430. $order['uid'], $product->title,
  431. $nickname,
  432. $pink['add_time'],
  433. $pink['people'],
  434. '/pages/order_details/index?order_id=' . $pink['order_id']
  435. );
  436. }
  437. //处理拼团完成
  438. list($pinkAll, $pinkT, $count, $idAll, $uidAll) = self::getPinkMemberAndPinkK($pink);
  439. if ($pinkT['status'] == 1) {
  440. if (!$count)//组团完成
  441. self::PinkComplete($uidAll, $idAll, $pink['uid'], $pinkT);
  442. else
  443. self::PinkFail($pinkAll, $pinkT, 0);
  444. }
  445. if ($res) return true;
  446. else return false;
  447. } else {
  448. $res = false;
  449. $pink['uid'] = $order['uid'];//用户id
  450. $pink['order_id'] = $order['order_id'];//订单id 生成
  451. $pink['order_id_key'] = $order['id'];//订单id 数据库id
  452. $pink['total_num'] = $order['total_num'];//购买个数
  453. $pink['total_price'] = $order['pay_price'];//总金额
  454. $pink['k_id'] = 0;//拼团id
  455. foreach ($order['cartInfo'] as $v) {
  456. $pink['cid'] = $v['combination_id'];//拼团商品id
  457. $pink['pid'] = $v['product_id'];//商品id
  458. $pink['people'] = StoreCombination::where('id', $v['combination_id'])->value('people');//几人拼团
  459. $pink['price'] = $v['productInfo']['price'];//单价
  460. $pink['stop_time'] = bcadd(time(), bcmul($product->effective_time, 3600, 0), 0);//结束时间
  461. $pink['add_time'] = time();//开团时间
  462. $pink['mer_id'] = $order['mer_id'];//所属商户
  463. $res1 = self::create($pink)->toArray();
  464. $res2 = StoreOrder::where('id', $order['id'])->update(['pink_id' => $res1['id']]);
  465. $res = $res1 && $res2;
  466. $pink['id'] = $res1['id'];
  467. }
  468. // 开团成功发送模板消息
  469. if ($openid && $order['is_channel'] != 1) { //公众号模板消息
  470. // $urlWeChat = Route::buildUrl('/order/detail/' . $pink['order_id'])->suffix('')->domain(true)->build();
  471. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::OPEN_PINK_SUCCESS, [
  472. // 'first' => '您好,您已成功开团!赶紧与小伙伴们分享吧!!!',
  473. // 'keyword1' => $product->title,
  474. // 'keyword2' => $pink['total_price'],
  475. // 'keyword3' => $pink['people'],
  476. // 'remark' => '点击查看订单详情'
  477. // ], $urlWeChat);
  478. $wechatTemplate = new WechatTemplate();
  479. $wechatTemplate->sendOrderPinkOpenSuccess($order['uid'], $pink, $product->title);
  480. } else if ($routineOpenid && $order['is_channel'] == 1) {
  481. $nickname = User::where('uid', $order['uid'])->value('nickname');
  482. RoutineTemplate::sendPinkSuccess(
  483. $order['uid'], $product->title,
  484. $nickname,
  485. $pink['add_time'],
  486. $pink['people'],
  487. '/pages/order_details/index?order_id=' . $pink['order_id']
  488. );
  489. }
  490. if ($res) return true;
  491. else return false;
  492. }
  493. } else {
  494. Log::error('拼团支付成功读取商品数据失败订单号:' . $order['order_id']);
  495. return false;
  496. }
  497. }
  498. /*
  499. * 获取一条今天正在拼团的人的头像和名称
  500. * */
  501. public static function getPinkSecondOne()
  502. {
  503. $addTime = mt_rand(time() - 30000, time());
  504. return self::where('p.add_time', '>', $addTime)->alias('p')->where('p.status', 1)->join('User u', 'u.uid=p.uid')->field('u.nickname,u.avatar as src')->find();
  505. }
  506. /**
  507. * 拼团成功后给团长返佣金
  508. * @param int $id
  509. * @return bool
  510. */
  511. // public static function setRakeBackColonel($id = 0){
  512. // if(!$id) return false;
  513. // $pinkRakeBack = self::where('id',$id)->field('people,price,uid,id')->find()->toArray();
  514. // $countPrice = bcmul($pinkRakeBack['people'],$pinkRakeBack['price'],2);
  515. // if(bcsub((float)$countPrice,0,2) <= 0) return true;
  516. // $rakeBack = (SystemConfigService::get('rake_back_colonel') ?: 0)/100;
  517. // if($rakeBack <= 0) return true;
  518. // $rakeBackPrice = bcmul($countPrice,$rakeBack,2);
  519. // if($rakeBackPrice <= 0) return true;
  520. // $mark = '拼团成功,奖励佣金'.floatval($rakeBackPrice);
  521. // self::beginTrans();
  522. // $res1 = UserBill::income('获得拼团佣金',$pinkRakeBack['uid'],'now_money','colonel',$rakeBackPrice,$id,0,$mark);
  523. // $res2 = User::bcInc($pinkRakeBack['uid'],'now_money',$rakeBackPrice,'uid');
  524. // $res = $res1 && $res2;
  525. // self::checkTrans($res);
  526. // return $res;
  527. // }
  528. /*
  529. * 拼团完成更改数据写入内容
  530. * @param array $uidAll 当前拼团uid
  531. * @param array $idAll 当前拼团pink_id
  532. * @param array $pinkT 团长信息
  533. * @return int
  534. * */
  535. public static function PinkComplete($uidAll, $idAll, $uid, $pinkT)
  536. {
  537. $pinkBool = 6;
  538. try {
  539. if (self::setPinkStatus($idAll)) {
  540. self::setPinkStopTime($idAll);
  541. if (in_array($uid, $uidAll)) {
  542. if (self::isTpl($uidAll, $pinkT['id'])) self::orderPinkAfter($uidAll, $pinkT['id']);
  543. $pinkBool = 1;
  544. } else $pinkBool = 3;
  545. }
  546. return $pinkBool;
  547. } catch (\Exception $e) {
  548. self::setErrorInfo($e->getMessage());
  549. return $pinkBool;
  550. }
  551. }
  552. /*
  553. * 拼团失败 退款
  554. * @param array $pinkAll 拼团数据,不包括团长
  555. * @param array $pinkT 团长数据
  556. * @param int $pinkBool
  557. * @param boolen $isRunErr 是否返回错误信息
  558. * @param boolen $isIds 是否返回记录所有拼团id
  559. * @return int| boolen
  560. * */
  561. public static function PinkFail($pinkAll, $pinkT, $pinkBool, $isRunErr = true, $isIds = false)
  562. {
  563. self::startTrans();
  564. $pinkIds = [];
  565. try {
  566. if ($pinkT['stop_time'] < time()) {//拼团时间超时 退款
  567. $pinkBool = -1;
  568. array_push($pinkAll, $pinkT);
  569. foreach ($pinkAll as $v) {
  570. if (StoreOrder::orderApplyRefund(StoreOrder::getPinkOrderId($v['order_id_key']), $v['uid'], '拼团时间超时') && self::isTpl($v['uid'], $pinkT['id'])) {
  571. if ($isIds) array_push($pinkIds, $v['id']);
  572. self::orderPinkAfterNo($pinkT['uid'], $pinkT['id']);
  573. } else {
  574. if ($isRunErr) return $pinkBool;
  575. }
  576. }
  577. }
  578. self::commit();
  579. if ($isIds) return $pinkIds;
  580. return $pinkBool;
  581. } catch (\Exception $e) {
  582. self::rollback();
  583. return $pinkBool;
  584. }
  585. }
  586. /*
  587. * 获取参团人和团长和拼团总人数
  588. * @param array $pink
  589. * @return array
  590. * */
  591. public static function getPinkMemberAndPinkK($pink)
  592. {
  593. //查找拼团团员和团长
  594. if ($pink['k_id']) {
  595. $pinkAll = self::getPinkMember($pink['k_id']);
  596. $pinkT = self::getPinkUserOne($pink['k_id']);
  597. } else {
  598. $pinkAll = self::getPinkMember($pink['id']);
  599. $pinkT = $pink;
  600. }
  601. $pinkT = $pinkT->hidden(['order_id', 'total_price', 'cid', 'pid', 'add_time', 'k_id', 'is_tpl', 'is_refund'])->toArray();
  602. $pinkAll = $pinkAll->hidden(['total_price', 'cid', 'pid', 'add_time', 'k_id', 'is_tpl', 'is_refund'])->toArray();
  603. $count = (int)bcadd(count($pinkAll), 1, 0);
  604. $count = (int)bcsub($pinkT['people'], $count, 0);
  605. $idAll = [];
  606. $uidAll = [];
  607. //收集拼团用户id和拼团id
  608. foreach ($pinkAll as $k => $v) {
  609. $idAll[$k] = $v['id'];
  610. $uidAll[$k] = $v['uid'];
  611. }
  612. $idAll[] = $pinkT['id'];
  613. $uidAll[] = $pinkT['uid'];
  614. return [$pinkAll, $pinkT, $count, $idAll, $uidAll];
  615. }
  616. /*
  617. * 取消开团
  618. * @param int $uid 用户id
  619. * @param int $pink_id 团长id
  620. * @return boolean
  621. * */
  622. public static function removePink($uid, $cid, $pink_id, $nextPinkT = null)
  623. {
  624. $pinkT = self::where('uid', $uid)
  625. ->where('id', $pink_id)
  626. ->where('cid', $cid)
  627. ->where('k_id', 0)
  628. ->where('is_refund', 0)
  629. ->where('status', 1)
  630. ->where('stop_time', '>', time())
  631. ->find();
  632. if (!$pinkT) return self::setErrorInfo('未查到拼团信息,无法取消');
  633. self::startTrans();
  634. try {
  635. list($pinkAll, $pinkT, $count, $idAll, $uidAll) = self::getPinkMemberAndPinkK($pinkT);
  636. if (count($pinkAll)) {
  637. if (self::getPinkPeople($pink_id, $pinkT['people'])) {
  638. //拼团未完成,拼团有成员取消开团取 紧跟团长后拼团的人
  639. if (isset($pinkAll[0])) $nextPinkT = $pinkAll[0];
  640. } else {
  641. //拼团完成
  642. self::PinkComplete($uidAll, $idAll, $uid, $pinkT);
  643. return self::setErrorInfo(['status' => 200, 'msg' => '拼团已完成,无法取消']);
  644. }
  645. }
  646. //取消开团
  647. if (StoreOrder::orderApplyRefund(StoreOrder::getPinkOrderId($pinkT['order_id_key']), $pinkT['uid'], '拼团取消开团') && self::isTpl($pinkT['uid'], $pinkT['id'])) {
  648. self::orderPinkAfterNo($pinkT['uid'], $pinkT['id'], '拼团取消开团', true);
  649. } else
  650. return self::setErrorInfo(['status' => 200, 'msg' => StoreOrder::getErrorInfo()], true);
  651. //当前团有人的时候
  652. if (is_array($nextPinkT)) {
  653. self::where('id', $nextPinkT['id'])->update(['k_id' => 0, 'status' => 1, 'stop_time' => $pinkT['stop_time']]);
  654. self::where('k_id', $pinkT['id'])->update(['k_id' => $nextPinkT['id']]);
  655. StoreOrder::where('order_id', $nextPinkT['order_id'])->update(['pink_id' => $nextPinkT['id']]);
  656. }
  657. self::commitTrans();
  658. return true;
  659. } catch (\Exception $e) {
  660. return self::setErrorInfo($e->getLine() . ':' . $e->getMessage() . ':' . $e->getFile(), true);
  661. }
  662. }
  663. /**
  664. * 获取用户拼团到结束时间后还是拼团中的拼团
  665. * @return mixed
  666. */
  667. public static function pinkListEnd()
  668. {
  669. $model = new self;
  670. $model = $model->field('id,people');//开团编号
  671. $model = $model->where('stop_time', '<=', time());//小于当前时间
  672. $model = $model->where('status', 1);//进行中的拼团
  673. $model = $model->where('k_id', 0);//团长
  674. $model = $model->where('is_refund', 0);//未退款
  675. return $model->select();
  676. }
  677. /**
  678. * 拼团成功
  679. * @param array $pinkRegimental 成功的团长编号
  680. * @return bool
  681. * @throws \Exception
  682. */
  683. public static function successPinkEdit(array $pinkRegimental)
  684. {
  685. if (!count($pinkRegimental)) return true;
  686. foreach ($pinkRegimental as $key => &$item) {
  687. $pinkList = self::where('k_id', $item)->column('id', 'id');
  688. $pinkList[] = $item;
  689. $pinkList = implode(',', $pinkList);
  690. self::setPinkStatus($pinkList);//修改完成状态
  691. self::setPinkStopTime($pinkList);//修改结束时间
  692. $pinkUidList = self::isTplPink($pinkList);//获取未发送模板消息的用户
  693. if (count($pinkUidList)) self::sendPinkTemplateMessageSuccess($pinkUidList, $item);//发送模板消息
  694. }
  695. return true;
  696. }
  697. /**
  698. * 拼团失败
  699. * @param array $pinkRegimental 失败的团长编号
  700. * @return bool
  701. * @throws DataNotFoundException
  702. * @throws ModelNotFoundException
  703. * @throws \think\exception\DbException
  704. */
  705. public static function failPinkEdit(array $pinkRegimental)
  706. {
  707. if (!count($pinkRegimental)) return true;
  708. foreach ($pinkRegimental as $key => &$item) {
  709. $pinkList = self::where('k_id', $item)->column('id', 'id');
  710. $pinkList[] = $item;
  711. $pinkList = implode(',', $pinkList);
  712. self::refundPink($pinkList);//申请退款
  713. self::pinkStopStatus($pinkList);//修改状态
  714. $pinkUidList = self::isTplPink($pinkList);//获取未发送模板消息的用户
  715. if (count($pinkUidList)) self::sendPinkTemplateMessageError($pinkUidList, $item);//发送模板消息
  716. }
  717. return true;
  718. }
  719. /**
  720. * 发送模板消息 失败
  721. * @param array $pinkUidList 拼团用户编号
  722. * @param $pink 团长编号
  723. * @throws DataNotFoundException
  724. * @throws ModelNotFoundException
  725. * @throws \think\exception\DbException
  726. */
  727. public static function sendPinkTemplateMessageError(array $pinkUidList, $pink)
  728. {
  729. foreach ($pinkUidList as $key => &$item) {
  730. $openid = WechatUser::uidToOpenid($item, 'openid');
  731. $routineOpenid = WechatUser::uidToOpenid($item, 'routine_openid');
  732. $store = self::alias('p')->where('p.id|p.k_id', $pink)->field('c.*')->where('p.uid', $item)->join('store_combination c', 'c.id=p.cid')->find();
  733. $pink = self::where('id|k_id', $pink)->where('uid', $item)->find();
  734. if ($openid) {
  735. //公众号模板消息
  736. // $urlWeChat = Route::buildUrl('order/detail/' . $pink->order_id)->suffix('')->domain(true)->build();
  737. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_LOSE, [
  738. // 'first' => '亲,您的拼团失败',
  739. // 'keyword1' => $store->title,
  740. // 'keyword2' => $pink->price,
  741. // 'keyword3' => $pink->price,
  742. // 'remark' => '点击查看订单详情'
  743. // ], $urlWeChat);
  744. $wechatTemplate = new WechatTemplate();
  745. $wechatTemplate->sendOrderPinkFial($item, $pink, $store->title);
  746. } else if ($routineOpenid) {
  747. //小程序模板消息
  748. RoutineTemplate::sendOut('PINK_Fill', $item, [
  749. 'keyword1' => $store->title,
  750. 'keyword2' => '拼团取消开团',
  751. 'keyword3' => $pink->order_id,
  752. 'keyword4' => date('Y-m-d H:i:s', $pink->add_time),
  753. 'keyword5' => '申请退款金额:¥' . $pink->price,
  754. ], '', '/pages/order_details/index?order_id=' . $pink->order_id);
  755. }
  756. }
  757. self::where('uid', 'IN', implode(',', $pinkUidList))->where('id|k_id', $pink)->update(['is_tpl' => 1]);
  758. }
  759. /**
  760. * 拼团失败 申请退款
  761. * @param $pinkList
  762. * @return bool
  763. */
  764. public static function refundPink($pinkList)
  765. {
  766. $refundPinkList = self::where('id', 'IN', $pinkList)->column('order_id,uid', 'id');
  767. if (!count($refundPinkList)) return true;
  768. foreach ($refundPinkList as $key => &$item) {
  769. StoreOrder::orderApplyRefund($item['order_id'], $item['uid'], '拼团时间超时');//申请退款
  770. }
  771. }
  772. /**
  773. * 拼团结束修改状态
  774. * @param $pinkList
  775. * @return StorePink
  776. */
  777. public static function pinkStopStatus($pinkList)
  778. {
  779. return self::where('id', 'IN', $pinkList)->update(['status' => 3]);
  780. }
  781. /**
  782. * 获取未发送模板消息的用户
  783. * @param $pinkList 拼团编号
  784. * @return array
  785. */
  786. public static function isTplPink($pinkList)
  787. {
  788. return self::where('id', 'IN', $pinkList)->where('is_tpl', 0)->column('uid', 'uid');
  789. }
  790. /**
  791. * 发送模板消息 成功
  792. * @param array $pinkUidList 拼团用户编号
  793. * @param $pink 团长编号
  794. * @throws \Exception
  795. */
  796. public static function sendPinkTemplateMessageSuccess(array $pinkUidList, $pink)
  797. {
  798. foreach ($pinkUidList as $key => &$item) {
  799. $openid = WechatUser::uidToOpenid($item, 'openid');
  800. $routineOpenid = WechatUser::uidToOpenid($item, 'routine_openid');
  801. $nickname = WechatUser::uidToOpenid(self::where('id', $pink)->value('uid'), 'nickname');
  802. if ($openid) {
  803. //公众号模板消息
  804. // $firstWeChat = '亲,您的拼团已经完成了';
  805. $keyword1WeChat = self::where('id|k_id', $pink)->where('uid', $item)->value('order_id');
  806. $keyword2WeChat = self::alias('p')->where('p.id|p.k_id', $pink)->where('p.uid', $item)->join('store_combination c', 'c.id=p.cid')->value('c.title');
  807. // $remarkWeChat = '点击查看订单详情';
  808. // $urlWeChat = Route::buildUrl('order/detail/' . $keyword1WeChat)->suffix('')->domain(true)->build();
  809. // WechatTemplateService::sendTemplate($openid, WechatTemplateService::ORDER_USER_GROUPS_SUCCESS, [
  810. // 'first' => $firstWeChat,
  811. // 'keyword1' => $keyword1WeChat,
  812. // 'keyword2' => $keyword2WeChat,
  813. // 'remark' => $remarkWeChat
  814. // ], $urlWeChat);
  815. $wechatTemplate = new WechatTemplate();
  816. $wechatTemplate->sendOrderPinkSuccess($item, $keyword1WeChat, $keyword2WeChat, $pink);
  817. } else if ($routineOpenid) {
  818. //小程序模板消息
  819. $pinkInfo = self::where('k.id|k.k_id', $pink)->alias('k')->where('k.uid', $item)
  820. ->field(['k.order_id', 'k.people', 'k.add_time', 'c.title'])
  821. ->join('store_combination c', 'c.id = k.cid')->find();
  822. RoutineTemplate::sendPinkSuccess(
  823. $item, $pinkInfo['title'] ?? '',
  824. $nickname,
  825. $pinkInfo['add_time'] ?? 0,
  826. $pinkInfo['people'] ?? 0,
  827. '/pages/order_details/index?order_id=' . $pinkInfo['order_id'] ?? ''
  828. );
  829. }
  830. }
  831. self::where('uid', 'IN', implode(',', $pinkUidList))->where('id|k_id', $pink)->update(['is_tpl' => 1]);
  832. }
  833. /**
  834. * 修改到期的拼团状态
  835. * @return bool
  836. * @throws DataNotFoundException
  837. * @throws ModelNotFoundException
  838. * @throws \think\exception\DbException
  839. */
  840. public static function statusPink()
  841. {
  842. $pinkListEnd = self::pinkListEnd();
  843. if (!$pinkListEnd) return true;
  844. $pinkListEnd = $pinkListEnd->toArray();
  845. $failPinkList = [];//拼团失败
  846. $successPinkList = [];//拼团失败
  847. foreach ($pinkListEnd as $key => &$value) {
  848. $countPeople = (int)bcadd(self::where('k_id', $value['id'])->count(), 1, 0);
  849. if ($countPeople == $value['people'])
  850. $successPinkList[] = $value['id'];
  851. else
  852. $failPinkList[] = $value['id'];
  853. }
  854. $success = self::successPinkEdit($successPinkList);
  855. $error = self::failPinkEdit($failPinkList);
  856. $res = $success && $error;
  857. return $res;
  858. }
  859. /**
  860. * 获取当前商品参与的人数
  861. * @param int $combinationId
  862. * @return int|string
  863. */
  864. public static function getCountPeopleAll($combinationId = 0, $mer_id = '')
  865. {
  866. if (!$combinationId) return self::merSet($mer_id)->where('status', 2)->count();
  867. return self::merSet($mer_id)->where('cid', $combinationId)->where('status', 2)->count();
  868. }
  869. /**
  870. * 获取当前商品参与的团数
  871. * @param int $combinationId
  872. * @return int|string
  873. */
  874. public static function getCountPeoplePink($combinationId = 0, $mer_id = '')
  875. {
  876. if (!$combinationId) return self::merSet($mer_id)->where('k_id', 0)->where('status', 2)->count();
  877. return self::merSet($mer_id)->where('cid', $combinationId)->where('k_id', 0)->where('status', 2)->count();
  878. }
  879. }