CouponController.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. <?php
  2. namespace addons\Store\console\controllers;
  3. use addons\Coupon\AddonConfig;
  4. use addons\Coupon\common\enums\AddonsCouponEnum;
  5. use addons\Coupon\common\models\AddonsCoupon;
  6. use addons\Coupon\common\models\AddonsCouponGoodStatistics;
  7. use addons\Coupon\common\models\AddonsCouponRemind;
  8. use addons\Coupon\common\models\AddonsCouponStatistics;
  9. use addons\Coupon\common\models\AddonsCouponUseLog;
  10. use addons\Coupon\common\models\AddonsCouponUserRelate;
  11. use addons\Store\common\enums\StoreEnum;
  12. use addons\Store\common\models\StoreCoupon;
  13. use addons\Store\common\models\StoreCouponGoodStatistics;
  14. use addons\Store\common\models\StoreCouponRemind;
  15. use addons\Store\common\models\StoreCouponStatistics;
  16. use addons\Store\common\models\StoreCouponUseLog;
  17. use addons\Store\common\models\StoreCouponUserRelate;
  18. use addons\Store\common\models\StoreOrder;
  19. use addons\Store\common\models\StoreOrderDetail;
  20. use common\enums\OrderStatusEnum;
  21. use common\enums\StatusEnum;
  22. use common\helpers\LockHelper;
  23. use common\helpers\wechat\WechatTemplate;
  24. use common\models\mall\Mall;
  25. use common\models\mall\MallAddons;
  26. use common\models\order\Order;
  27. use common\models\order\OrderDetail;
  28. use common\models\order\OrderMarketing;
  29. use yii\console\Controller;
  30. use yii\console\ExitCode;
  31. class CouponController extends Controller
  32. {
  33. /**
  34. * 自动更新门店优惠券状态,定时器调用执行
  35. *
  36. */
  37. // 0 */1 * * * *
  38. public function actionUpdateCouponStatus()
  39. {
  40. try {
  41. echo ' 自动更新门店优惠券状态任务开始执行 ... ' . PHP_EOL;
  42. // 获取当前系统所有可用的 mall_id
  43. $malls = Mall::getEnableMallList();
  44. $mall_ids = array_column($malls, 'id');
  45. echo ' 获取到的 mall_id => ' . implode(', ', $mall_ids) . PHP_EOL;
  46. foreach ($mall_ids as $mall_id) {
  47. echo '开始更新商城的门店优惠券:mall_id => ' . $mall_id . PHP_EOL;
  48. $obj = new AddonConfig();
  49. $name = ($obj->info)['name'];
  50. // 更新门店优惠券主表
  51. $lock_name_main = 'qimall:update_store_coupon_status:main:mall_id:' . $mall_id;
  52. $lock_val_main = md5($lock_name_main);
  53. $lock_main = LockHelper::lock($lock_name_main, $lock_val_main, 60);
  54. $lock_main && self::updateMainCoupons($mall_id);
  55. LockHelper::uLock($lock_name_main, $lock_val_main);
  56. // 更新会员已经领取的门店优惠券的状态
  57. $lock_name_user = 'qimall:update_store_coupon_status:user:mall_id:' . $mall_id;
  58. $lock_val_user = md5($lock_name_user);
  59. $lock_user = LockHelper::lock($lock_name_user, $lock_val_user, 60);
  60. $lock_user && self::updateUserCoupons($mall_id);
  61. LockHelper::uLock($lock_name_user, $lock_val_user);
  62. }
  63. echo ' 自动更新门店优惠券状态任务执行完毕 ... ' . PHP_EOL;
  64. return ExitCode::OK;
  65. } catch (\Exception $e) {
  66. LockHelper::uLock($lock_name_main, $lock_val_main);
  67. LockHelper::uLock($lock_name_user, $lock_val_user);
  68. $errmsg = ' 自动更新门店优惠券状态任务执行出错, errmsg => ' . $e->getMessage() . ', file: ' . $e->getFile() . ', line: ' . $e->getLine();
  69. echo $errmsg . PHP_EOL;
  70. \Yii::error($errmsg);
  71. \Yii::getLogger()->flush(true);
  72. return false;
  73. }
  74. }
  75. /**
  76. * 门店优惠券相关统计,定时器调用执行
  77. *
  78. */
  79. // 0 */3 * * * *
  80. public function actionCouponStatistics()
  81. {
  82. // \Yii::error('门店优惠券相关统计任务开始执行 ... ');
  83. // \Yii::getLogger()->flush(true);
  84. try {
  85. echo ' 门店优惠券相关统计任务开始执行 ... ' . PHP_EOL;
  86. // 获取当前系统所有可用的 mall_id
  87. $malls = Mall::getEnableMallList();
  88. $mall_ids = array_column($malls, 'id');
  89. echo ' 获取到的 mall_id => ' . implode(', ', $mall_ids) . PHP_EOL;
  90. // foreach ($mall_ids as $mall_id) {
  91. $mall_id = 5;
  92. echo '开始更新商城的门店优惠券:mall_id => ' . $mall_id . PHP_EOL;
  93. $obj = new AddonConfig();
  94. $name = ($obj->info)['name'];
  95. $is_install = MallAddons::isInstall($mall_id, $name);
  96. // if (!$is_install) continue;
  97. $lock_name = 'qimall:coupon_statistics:mall_id:' . $mall_id;
  98. $lock_val = md5($lock_name);
  99. // $lock = LockHelper::lock($lock_name, $lock_val, 60);
  100. // if ($lock) {
  101. // 门店优惠券相关数量
  102. self::statNumber($mall_id);
  103. // 订单使用相关统计
  104. self::statOrder($mall_id);
  105. // 计算门店优惠券使用率
  106. self::calUseProbability($mall_id);
  107. // }
  108. // LockHelper::uLock($lock_name, $lock_val);
  109. // }
  110. echo ' 门店优惠券相关统计任务执行完毕' . PHP_EOL;
  111. return ExitCode::OK;
  112. } catch (\Exception $e) {
  113. // LockHelper::uLock($lock_name, $lock_val);
  114. $errmsg = $e->getMessage() . ', file: ' . $e->getFile() . ', line: ' . $e->getLine();
  115. \Yii::error($errmsg);
  116. \Yii::getLogger()->flush(true);
  117. return false;
  118. }
  119. }
  120. /**
  121. * 统计商品使用门店优惠券相关数据,定时器调用执行
  122. *
  123. */
  124. // 0 */3 * * * *
  125. public function actionCouponGoodStat()
  126. {
  127. // \Yii::error('统计商品使用门店优惠券相关数据任务开始执行 ...');
  128. // \Yii::getLogger()->flush(true);
  129. try {
  130. echo ' 统计商品使用门店优惠券相关数据任务开始执行 ... ' . PHP_EOL;
  131. // 获取当前系统所有可用的 mall_id
  132. $malls = Mall::getEnableMallList();
  133. $mall_ids = array_column($malls, 'id');
  134. echo ' 获取到的 mall_id => ' . implode(', ', $mall_ids) . PHP_EOL;
  135. foreach ($mall_ids as $mall_id) {
  136. echo ' 开始更新商城的门店优惠券:mall_id => ' . $mall_id . PHP_EOL;
  137. // $mall_id = 5;
  138. $obj = new AddonConfig();
  139. $name = ($obj->info)['name'];
  140. $is_install = MallAddons::isInstall($mall_id, $name);
  141. if (!$is_install) {
  142. echo ' 未安装门店优惠券应用' . PHP_EOL;
  143. continue;
  144. }
  145. $lock_name = 'qimall:coupon_good_stat:mall_id:' . $mall_id;
  146. $lock_val = md5($lock_name);
  147. $lock = LockHelper::lock($lock_name, $lock_val, 60);
  148. if ($lock) {
  149. // 统计使用门店优惠券购买商品相关数量
  150. self::statBookNumber($mall_id);
  151. } else {
  152. echo ' 获取锁失败' . PHP_EOL;
  153. }
  154. LockHelper::uLock($lock_name, $lock_val);
  155. }
  156. echo ' 统计商品使用门店优惠券相关数据任务执行完毕' . PHP_EOL;
  157. return ExitCode::OK;
  158. } catch (\Exception $e) {
  159. LockHelper::uLock($lock_name, $lock_val);
  160. $errmsg = $e->getMessage() . ', file: ' . $e->getFile() . ', line: ' . $e->getLine();
  161. \Yii::error($errmsg);
  162. \Yii::getLogger()->flush(true);
  163. return false;
  164. }
  165. }
  166. /**
  167. * 门店优惠券过期前提醒,定时器调用执行
  168. */
  169. // 0 0 */4 * * *
  170. public function actionExpireRemind()
  171. {
  172. try {
  173. // 获取当前系统所有可用的 mall_id
  174. $malls = Mall::getEnableMallList();
  175. $mall_ids = array_column($malls, 'id');
  176. echo ' 获取到的 mall_id => ' . implode(', ', $mall_ids) . PHP_EOL;
  177. foreach ($mall_ids as $mall_id) {
  178. echo '开始更新商城的门店优惠券:mall_id => ' . $mall_id . PHP_EOL;
  179. // $mall_id = 5;
  180. $obj = new AddonConfig();
  181. $name = ($obj->info)['name'];
  182. $is_install = MallAddons::isInstall($mall_id, $name);
  183. if (!$is_install) continue;
  184. $page = 1;
  185. $limit = 500;
  186. do {
  187. $offset = ($page - 1) * $limit;
  188. $page++;
  189. $reminds = AddonsCouponRemind::find()
  190. ->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'send_status' => 1])
  191. ->limit($limit)
  192. ->offset($offset)
  193. ->all();
  194. if (!empty($reminds)) {
  195. foreach ($reminds as $remind) {
  196. $coupon = AddonsCoupon::findOne(['id' => $remind->coupon_id, 'mall_id' => $mall_id, 'is_remind' => 1]);
  197. if (empty($coupon)) continue;
  198. $time_node = $remind->remind_days * 86400;
  199. if ($time_node > $remind->expire_time) {
  200. // 现在到门店优惠券过期的时间小于三天,发消息提醒
  201. $params = [
  202. 'mall_id' => $mall_id,
  203. 'user_id' => $remind->user_id,
  204. 'first' => '您已经领取的门店优惠券',
  205. 'keywords' => [
  206. 'keyword1' => $coupon->name,
  207. ],
  208. 'remark' => '即将过期,请尽快使用。'
  209. ];
  210. // self::sendWechatMessage($params);
  211. }
  212. // 睡眠 1s,防止腾讯封禁
  213. sleep(1);
  214. }
  215. }
  216. } while ($reminds);
  217. }
  218. echo ' 发送过期提醒任务执行完毕 ... ' . PHP_EOL;
  219. return true;
  220. } catch (\Exception $e) {
  221. $errmsg = $e->getMessage() . ', file: ' . $e->getFile() . ', line: ' . $e->getLine();
  222. \Yii::error($errmsg);
  223. \Yii::getLogger()->flush(true);
  224. return false;
  225. }
  226. }
  227. //更新门店优惠券主表中的状态
  228. private static function updateMainCoupons(int $mall_id)
  229. {
  230. $curr_time = time();
  231. $receiving_ids = [];
  232. $finished_receive_ids = [];
  233. $page = 1;
  234. $limit = 500;
  235. do {
  236. $offset = ($page - 1) * $limit;
  237. $page++;
  238. $coupons = StoreCoupon::find()
  239. ->where(['mall_id' => $mall_id, 'status' => 1, 'expire_type' => 2])
  240. ->andWhere(['!=', 'coupon_status', 4])
  241. ->limit($limit)
  242. ->offset($offset)
  243. ->all();
  244. if (!empty($coupons)) {
  245. foreach ($coupons as $coupon) {
  246. if ($coupon['begin_at'] <= $curr_time && $coupon['end_at'] > $curr_time) {
  247. // 门店优惠券领取中
  248. $receiving_ids[] = $coupon['id'];
  249. } elseif ($coupon['end_at'] <= $curr_time) {
  250. $finished_receive_ids[] = $coupon['id'];
  251. }
  252. }
  253. }
  254. } while ($coupons);
  255. if (!empty($receiving_ids)) {
  256. $res = StoreCoupon::updateAll(['coupon_status' => 2], ['id' => $receiving_ids, 'mall_id' => $mall_id]);
  257. if ($res === false) {
  258. \Yii::error('更新门店优惠券状态失败:res => ' . var_export($res, true) . ', mall_id => ' . $mall_id . ', receiving_ids => ' . var_export($receiving_ids, true) . ', errmsg => ' . AddonsCoupon::getStaticError());
  259. \Yii::getLogger()->flush(true);
  260. }
  261. }
  262. if (!empty($finished_receive_ids)) {
  263. $res = StoreCoupon::updateAll(['coupon_status' => 3], ['id' => $finished_receive_ids, 'mall_id' => $mall_id]);
  264. $res_remaind = StoreCouponRemind::updateAll(['send_status' => 3], ['coupon_id' => $finished_receive_ids, 'mall_id' => $mall_id]);
  265. $res_uc = StoreCouponUserRelate::updateAll(['coupon_status' => 3], ['coupon_id' => $finished_receive_ids, 'mall_id' => $mall_id]);
  266. if ($res === false || $res_remaind === false || $res_uc === false) {
  267. \Yii::error('更新门店优惠券状态失败:res => ' . var_export($res, true) . ', res_remaind => ' . var_export($res_remaind, true) . ', res_uc => ' . var_export($res_uc, true) . ', mall_id => ' . $mall_id . ', finished_receive_ids => ' . var_export($finished_receive_ids, true) . ', ac_errmsg => ' . StoreCoupon::getStaticCodeError() . ', cr_errmsg => ' . StoreCouponRemind::getStaticError() . ', cu_errmsg => ' . StoreCouponUserRelate::getStaticError());
  268. \Yii::getLogger()->flush(true);
  269. }
  270. }
  271. }
  272. /**
  273. * @name:
  274. * @msg: 更新会员已经领取的门店优惠券的状态
  275. * @param {int} $mall_id
  276. * @return {*}
  277. */
  278. private static function updateUserCoupons(int $mall_id)
  279. {
  280. $time = time();
  281. $page = 1;
  282. $limit = 500;
  283. do {
  284. $offset = ($page - 1) * $limit;
  285. $page++;
  286. $user_coupons = StoreCouponUserRelate::find()
  287. ->where(['mall_id' => $mall_id, 'is_use' => 0, 'status' => 1, 'is_force_failure' => 0, 'coupon_status' => StoreEnum::STATUS_RECEIVING])
  288. ->andWhere(['or', ['is_giving' => 0], ['is_giving' => 1, 'giving_status' => 1]])
  289. ->andWhere(['<=', 'end_time', $time])
  290. ->limit($limit)
  291. ->offset($offset)
  292. ->all();
  293. if (!empty($user_coupons)) {
  294. foreach ($user_coupons as $user_coupon) {
  295. $user_coupon->coupon_status = StoreEnum::STATUS_EXPIRED;
  296. $user_coupon->updated_at = $time;
  297. $res = $user_coupon->save();
  298. if (!$res) {
  299. $errmsg = ' 更新门店优惠券状态失败:res => ' . var_export($res, true) . ', mall_id => ' . $mall_id . ', id => ' . $user_coupon->id;
  300. echo $errmsg . PHP_EOL;
  301. \Yii::error($errmsg);
  302. \Yii::getLogger()->flush(true);
  303. }
  304. }
  305. }
  306. } while ($user_coupons);
  307. }
  308. /**
  309. * @name:
  310. * @msg: 统计商品使用门店优惠券相关数据
  311. * @param {int} $mall_id
  312. * @param {string} $type
  313. * @param {string} $field
  314. * @return {*}
  315. */
  316. private static function statBookNumber(int $mall_id)
  317. {
  318. $stat_datas = $booking_users = $payed_users = $booking_number = [];
  319. $page = 1;
  320. $limit = 500;
  321. do {
  322. $offset = ($page - 1) * $limit;
  323. $page++;
  324. $coupons = StoreCoupon::find()->where(['mall_id' => $mall_id, 'status' => 1])->limit($limit)->offset($offset)->all();
  325. if (!empty($coupons)) {
  326. $coupon_ids = array_column($coupons, 'id');
  327. if (empty($coupon_ids)) continue;
  328. $coupon_use_log = StoreCouponUseLog::find()
  329. ->select('order_id,coupon_id,user_coupon_id')
  330. ->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'coupon_id' => $coupon_ids])
  331. ->asArray()
  332. ->indexBy('order_id')
  333. ->all();
  334. $order_ids = array_column($coupon_use_log, 'order_id');
  335. $orders = StoreOrder::find()
  336. ->where(['id' => $order_ids, 'status' => StatusEnum::ENABLED])
  337. ->asArray()
  338. ->indexBy('id')
  339. ->all();
  340. if (empty($orders)) continue;
  341. $order_details = StoreOrderDetail::find()
  342. ->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'order_id' => array_column($orders, 'id')])
  343. ->all();
  344. foreach ($order_details as $detail) {
  345. $coupon_id = $coupon_use_log[$detail->order_id]['coupon_id'] ?? 0;
  346. $key_order_number = $coupon_id . '_' . $detail['goods_id'];
  347. // 下单数量
  348. $booking_number[$key_order_number][] = $detail->order_id;
  349. // 支付数量
  350. $pay_status = $orders[$detail->order_id]['pay_status'] ?? OrderStatusEnum::NOT_PAY;
  351. if ($pay_status == OrderStatusEnum::PAY) $payed_number[$key_order_number][] = $detail->order_id;
  352. // 下单总人数
  353. $booking_users[$key_order_number][] = $detail->user_id;
  354. // 购买总人数
  355. if ($pay_status == OrderStatusEnum::PAY) $payed_users[$key_order_number][] = $detail->user_id;
  356. }
  357. }
  358. } while ($coupons);
  359. if (!empty($booking_number)) {
  360. foreach ($booking_number as $key => $order_ids) {
  361. $stat_datas[$key]['booking_number'] = count(array_values(array_unique($order_ids)));
  362. }
  363. }
  364. if (!empty($payed_number)) {
  365. foreach ($payed_number as $key => $order_ids) {
  366. $stat_datas[$key]['payed_number'] = count(array_values(array_unique($order_ids)));
  367. }
  368. }
  369. if (!empty($booking_users)) {
  370. foreach ($booking_users as $key => $users) {
  371. $stat_datas[$key]['booking_user_number'] = count(array_values(array_unique($users)));
  372. }
  373. }
  374. if (!empty($payed_users)) {
  375. foreach ($payed_users as $key => $users) {
  376. $stat_datas[$key]['buyed_user_number'] = count(array_values(array_unique($users)));
  377. }
  378. }
  379. if (empty($stat_datas)) {
  380. echo ' stat_datas is empty, stat_datas => ' . var_export($stat_datas, true) . PHP_EOL;
  381. return;
  382. }
  383. // self::updateCouponGoodStat($stat_datas, $mall_id);
  384. }
  385. /**
  386. * @name:
  387. * @msg: 更新门店优惠券商品统计表
  388. * @param {array} $data
  389. * @param {int} $mall_id
  390. * @param {*} $field
  391. * @return {*}
  392. */
  393. private static function updateCouponGoodStat(array $data, int $mall_id)
  394. {
  395. if (!empty($data)) {
  396. foreach ($data as $key => $dv) {
  397. $keys = explode('_', $key);
  398. $coupon_good_stat = StoreCouponGoodStatistics::findOne(['mall_id' => $mall_id, 'coupon_id' => $keys[0], 'good_id' => $keys[1]]);
  399. if (empty($coupon_good_stat)) {
  400. $coupon_good_stat = new StoreCouponGoodStatistics();
  401. $data = [
  402. 'mall_id' => $mall_id,
  403. 'coupon_id' => $keys[0] ?? 0,
  404. 'good_id' => $keys[1] ?? 0,
  405. 'created_at' => time(),
  406. ];
  407. $coupon_good_stat->attributes = $data;
  408. }
  409. foreach ($dv as $dk => $val) {
  410. $coupon_good_stat->$dk = $val;
  411. }
  412. $res = $coupon_good_stat->save();
  413. if (!$res) {
  414. var_dump($coupon_good_stat->getErrorMessage());
  415. $errmsg = ' 插入/更新已领取数量失败, res => ' . $res . ', data => ' . var_export($data, true);
  416. echo $errmsg . PHP_EOL;
  417. \Yii::error($errmsg);
  418. \Yii::getLogger()->flush(true);
  419. }
  420. }
  421. }
  422. }
  423. /**
  424. * @name:
  425. * @msg: 统计数量
  426. * @param {int} $mall_id
  427. * @param {array} $conditions
  428. * @param {string} $field
  429. * @return {*}
  430. */
  431. private static function statNumber(int $mall_id)
  432. {
  433. echo ' 统计相关数量 ... ' . PHP_EOL;
  434. $user_coupons = [];
  435. $page = 1;
  436. $limit = 500;
  437. do {
  438. $offset = ($page - 1) * $limit;
  439. $page++;
  440. $use_coupons = StoreCouponUserRelate::find()->where(['mall_id' => $mall_id, 'status' => 1,'from_type'=>2])->limit($limit)->offset($offset)->all();
  441. if (!empty($use_coupons)) {
  442. foreach ($use_coupons as $key => $use_coupon) {
  443. $coupon_id = $use_coupon->coupon_id;
  444. // 统计已领取数量
  445. if (!isset($user_coupons[$coupon_id]['received_number'])) $user_coupons[$coupon_id]['received_number'] = 0;
  446. $user_coupons[$coupon_id]['received_number'] += 1;
  447. $user_coupons[$coupon_id]['store_id'] = $use_coupon['store_id'];
  448. // 统计已使用数量
  449. if (!isset($user_coupons[$coupon_id]['used_number'])) $user_coupons[$coupon_id]['used_number'] = 0;
  450. $use_coupon->is_use == 1 && $user_coupons[$coupon_id]['used_number'] += 1;
  451. // 统计门店优惠券被转赠的次数
  452. if (!isset($user_coupons[$coupon_id]['giveing_times'])) $user_coupons[$coupon_id]['giveing_times'] = 0;
  453. $use_coupon->is_giving == 1 && $user_coupons[$coupon_id]['giveing_times'] += 1;
  454. // 记录领取会员id
  455. $received_user_ids[$coupon_id][] = $use_coupon->user_id;
  456. // 记录使用会员id
  457. $use_coupon->is_use == 1 && $used_user_ids[$coupon_id][] = $use_coupon->user_id;
  458. // 记录转赠门店优惠券的会员id
  459. $use_coupon->is_giving == 1 && $giving_user_ids[$coupon_id][] = $use_coupon->user_id;
  460. }
  461. }
  462. } while ($use_coupons);
  463. // 统计领取会员数量
  464. if (!empty($received_user_ids)) {
  465. foreach ($received_user_ids as $coupon_id => $user_ids) {
  466. $counts = count(array_flip(array_flip($user_ids)));
  467. $user_coupons[$coupon_id]['receive_user_number'] = $counts;
  468. }
  469. }
  470. // 统计用券会员数量
  471. if (!empty($used_user_ids)) {
  472. foreach ($used_user_ids as $coupon_id => $user_ids) {
  473. $counts = count(array_flip(array_flip($user_ids)));
  474. $user_coupons[$coupon_id]['use_user_number'] = $counts;
  475. }
  476. }
  477. // 统计转赠门店优惠券的会员数量
  478. if (!empty($giving_user_ids)) {
  479. foreach ($giving_user_ids as $coupon_id => $user_ids) {
  480. $counts = count(array_flip(array_flip($user_ids)));
  481. $user_coupons[$coupon_id]['giving_user_number'] = $counts;
  482. }
  483. }
  484. !empty($user_coupons) && self::updateCouponStat($user_coupons, $mall_id);
  485. echo ' 统计相关数量完成 ... ' . PHP_EOL;
  486. }
  487. /**
  488. * @name:
  489. * @msg: 更新 jxmall_coupon_statistics 表数据
  490. * @param {array} $data 统计得到的结果
  491. * @param {int} $mall_id
  492. * @param {string} $field 更新字段名
  493. * @return {*}
  494. */
  495. private static function updateCouponStat(array $data, int $mall_id)
  496. {
  497. if (!empty($data)) {
  498. foreach ($data as $coupon_id => $dv) {
  499. $coupon_stat = StoreCouponStatistics::findOne(['mall_id' => $mall_id, 'coupon_id' => $coupon_id]);
  500. if (empty($coupon_stat)) {
  501. $coupon_stat = new StoreCouponStatistics();
  502. $data = [
  503. 'mall_id' => $mall_id,
  504. 'coupon_id' => $coupon_id,
  505. 'store_id' => $dv['store_id'],
  506. 'created_at' => time()
  507. ];
  508. $coupon_stat->attributes = $data;
  509. }
  510. foreach ($dv as $key => $value) {
  511. $coupon_stat->$key = $value;
  512. }
  513. // var_dump($coupon_stat);
  514. $res = $coupon_stat->save();
  515. if (!$res) {
  516. $errmsg = ' 插入/更新已领取数量失败, res => ' . $res . ', data => ' . var_export($data, true);
  517. echo $errmsg . PHP_EOL;
  518. \Yii::error($errmsg);
  519. \Yii::getLogger()->flush(true);
  520. }
  521. }
  522. }
  523. }
  524. /**
  525. * @name:
  526. * @msg: 计算门店优惠券使用率
  527. * @param {int} $mall_id
  528. * @return {*}
  529. */
  530. private static function calUseProbability(int $mall_id)
  531. {
  532. $page = 1;
  533. $limit = 500;
  534. do {
  535. $offset = ($page - 1) * $limit;
  536. $page++;
  537. $coupon_stats = StoreCouponStatistics::find()->where(['mall_id' => $mall_id])->limit($limit)->offset($offset)->all();
  538. if (!empty($coupon_stats)) {
  539. foreach ($coupon_stats as $coupon_stat) {
  540. if (empty($coupon_stat->received_number)) continue;
  541. $coupon_stat->use_probability = bcdiv($coupon_stat->used_number, $coupon_stat->received_number, 2);
  542. $res = $coupon_stat->save();
  543. if (!$res) {
  544. $errmsg = ' 计算&更新门店优惠券使用率出错:res => ' . var_export($res, true) . ', errmsg => ' . $coupon_stat->getErrorMessage() . ', mall_id => ' . $mall_id . ', coupon_id => ' . $coupon_stat->coupon_id;
  545. echo $errmsg . PHP_EOL;
  546. \Yii::error($errmsg);
  547. \Yii::getLogger()->flush(true);
  548. }
  549. }
  550. }
  551. } while ($coupon_stats);
  552. }
  553. // private static function sendWechatMessage(array $params)
  554. // {
  555. // $wechat = new WechatTemplate($params['mall_id']);
  556. // //商城是否开启推送模板消息
  557. // if ($wechat->is_logging() === false) {
  558. // return;
  559. // }
  560. // //用户是否开启模板消息
  561. // if ($wechat->is_notice($params['user_id']) === false) {
  562. // return;
  563. // }
  564. // //是否公众号用户
  565. // if ($wechat->is_platform_wechat($params['user_id']) === false) {
  566. // return;
  567. // }
  568. // $platform = $wechat->getPlatForm();
  569. //
  570. // $h5_domain = \Yii::$app->services->setting->mall->get($params['mall_id'], 'basic.web_url');
  571. // if (empty($h5_domain)) {
  572. // $h5_domain = \Yii::$app->request->hostInfo;
  573. // } else {
  574. // $h5_domain = substr($h5_domain, 0, strpos($h5_domain, '?'));
  575. // }
  576. // $url = 'pages/user/coupon/coupon';
  577. // $h5_url = $h5_domain . $url;
  578. // $send_data = [
  579. // 'first' => $params['first'],
  580. // 'remark' => $params['remark'],
  581. // ];
  582. // if (!empty($params['keywords'])) {
  583. // foreach ($params['keywords'] as $key => $val) {
  584. // $send_data[$key] = $val;
  585. // }
  586. // }
  587. // $temp_key = WechatTemplate::ORDER_CREATE;
  588. // $wechat->sendTemplate($params['user_id'], $temp_key, $h5_url, $send_data, $platform, $url);
  589. // }
  590. }