CouponCrontabController.php.bak 26 KB

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