PromotionDayCharge.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. namespace App\Console\Commands\Statistic;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Arr;
  5. use Illuminate\Support\Facades\DB;
  6. use Illuminate\Support\Facades\Redis;
  7. class PromotionDayCharge extends Command
  8. {
  9. /**
  10. * The name and signature of the console command.
  11. *
  12. * @var string
  13. */
  14. protected $signature = 'Statistic:PromotionDayCharge {--date= : 统计日期}';
  15. /**
  16. * The console command description.
  17. *
  18. * @var string
  19. */
  20. protected $description = '推广充值日统计';
  21. /**
  22. * Execute the console command.
  23. */
  24. public function handle(): void
  25. {
  26. $date = $this->option('date') ?? date('Y-m-d', strtotime('yesterday'));
  27. $optimizerDayData = [];
  28. DB::table('orders')
  29. ->whereBetween('created_at', [
  30. $date, $date. ' 23:59:59'
  31. ])->where('promotion_id', '<>', 0)
  32. ->distinct()
  33. ->select('promotion_id')
  34. ->orderBy('promotion_id')
  35. ->chunk(100, function ($items) use ($date, &$optimizerDayData){
  36. $promotionData = [];
  37. $now = date('Y-m-d H:i:s');
  38. $promotions = DB::table('promotions')
  39. ->leftJoin('users', 'users.id', '=' , 'promotions.uid')
  40. ->whereIn('promotions.id', $items->pluck('promotion_id'))
  41. ->select('promotions.id', 'promotions.uid', 'promotions.miniprogram_id', 'users.pid as puid')
  42. ->get()->keyBy('id');
  43. foreach ($items as $item) {
  44. $promotion = $promotions->get($item->promotion_id);
  45. if(!$promotion) {
  46. myLog('PromotionDayCharge')->error('订单中有的推广id,但是推广信息表中没有', ['promotion_id' => $item->promotion_id]);
  47. continue;
  48. }
  49. $promotionDayCharge = $this->promotionDayCharge($item->promotion_id, $date);
  50. $newUserCharge = $this->newUserCharge($item->promotion_id, $date);
  51. $chargeInfo = $this->getPromotionData($promotionDayCharge, $newUserCharge);
  52. $chargeInfo['new_user_num'] = $this->getNewUserNum($item->promotion_id, $date);
  53. $promotionData[] = array_merge( $chargeInfo, [
  54. 'promotion_id' => $item->promotion_id, 'day_at' => $date,
  55. 'created_at' => $now, 'updated_at' => $now,
  56. 'user_id' => $promotion->uid,'puser_id' => $promotion->puid,
  57. 'miniprogram_id' => $promotion->miniprogram_id,
  58. ]);
  59. $key = $promotion->uid . '-'. $promotion->miniprogram_id;
  60. foreach ($chargeInfo as $k => $v) {
  61. $optimizerDayData[$key][$k] = $optimizerDayData[$key][$k] ?? 0 + $v;
  62. $optimizerDayData[$key]['user_id'] = $promotion->uid;
  63. $optimizerDayData[$key]['puser_id'] = $promotion->puid;
  64. $optimizerDayData[$key]['miniprogram_id'] = $promotion->miniprogram_id;
  65. $optimizerDayData[$key]['day_at'] = $date;
  66. $optimizerDayData[$key]['created_at'] = $now;
  67. $optimizerDayData[$key]['updated_at'] = $now;
  68. }
  69. }
  70. DB::table('tj_promotion_day_charge')
  71. ->insert($promotionData);
  72. });
  73. foreach (collect($optimizerDayData)->chunk(100) as $items) {
  74. DB::table('tj_optimizer_day_charge')
  75. ->insert($items->values()->toArray());
  76. }
  77. }
  78. /**
  79. * 某个推广链接在某天的新用户数量
  80. * @param $promotionId 推广链接id
  81. * @param $date 日期
  82. * @return mixed
  83. */
  84. private function getNewUserNum($promotionId, $date) {
  85. return intval(Redis::hget(sprintf('promotion:newUserCount:%s', $date), $promotionId));
  86. }
  87. public function getPromotionData($promotionDayCharge, $newUserCharge) {
  88. return [
  89. 'pay_money' => $promotionDayCharge['pay_money'] ?? 0,
  90. 'pay_count' => $promotionDayCharge['pay_count'] ?? 0,
  91. 'common_pay_money' => $promotionDayCharge['common_pay_money'] ?? 0,
  92. 'common_pay_uv' => $promotionDayCharge['common_pay_uv'] ?? 0,
  93. 'common_pay_count' => $promotionDayCharge['common_pay_count'] ?? 0,
  94. 'common_unpay_count' => $promotionDayCharge['common_unpay_count'] ?? 0,
  95. 'vip_pay_money' => $promotionDayCharge['vip_pay_money'] ?? 0,
  96. 'vip_pay_uv' => $promotionDayCharge['vip_pay_uv'] ?? 0,
  97. 'vip_pay_count' => $promotionDayCharge['vip_pay_count'] ?? 0,
  98. 'vip_unpay_count' => $promotionDayCharge['vip_unpay_count'] ?? 0,
  99. 'new_user_pay_money' => $newUserCharge['new_user_pay_money'] ?? 0,
  100. 'new_user_common_pay_money' => $newUserCharge['new_user_common_pay_money'] ?? 0,
  101. 'new_user_vip_pay_money' => $newUserCharge['new_user_vip_pay_money'] ?? 0,
  102. 'new_user_pay_uv' => $newUserCharge['new_user_pay_uv'] ?? 0,
  103. 'new_user_vip_pay_uv' => $newUserCharge['new_user_vip_pay_uv'] ?? 0,
  104. 'new_user_common_pay_uv' =>$newUserCharge['new_user_common_pay_uv'] ?? 0,
  105. ];
  106. }
  107. public function newUserCharge($promotionId, $date) {
  108. $info = DB::table('orders')
  109. ->where('promotion_id', $promotionId)
  110. ->whereBetween('ranse_created_at', [$date, $date. ' 23:59:59'])
  111. ->whereBetween('created_at', [$date, $date. ' 23:59:59'])
  112. ->select(
  113. // 总支付金额
  114. DB::raw("sum(if(status <> 'unpaid', price, 0)) as pay_money"),
  115. // 普通支付金额
  116. DB::raw("sum(if(status <> 'unpaid' and order_type in ('coin', 'first_coin'), price, 0)) as common_pay_money"),
  117. // 累计充值人数
  118. DB::raw("count(distinct if(status <> 'unpaid', concat(uid, ranse_created_at), null)) as pay_uv"),
  119. // 普通支付人数
  120. DB::raw("count(distinct if(order_type in ('coin', 'first_coin') and status <> 'unpaid', concat(uid, ranse_created_at), null)) as common_pay_uv"),
  121. // vip支付人数
  122. DB::raw("count(distinct if(order_type not in ('coin', 'first_coin') and status <> 'unpaid', concat(uid, ranse_created_at), null)) as vip_pay_uv"),
  123. )->first();
  124. if($info) {
  125. return [
  126. // 新增用户支付总额
  127. 'new_user_pay_money' => $info->pay_money,
  128. // 新增用户普通支付总额
  129. 'new_user_common_pay_money' => $info->common_pay_money,
  130. // 新增用户会员支付总额
  131. 'new_user_vip_pay_money' => $info->pay_money - $info->common_pay_money,
  132. // 新增用户在{$date}充值人数
  133. 'new_user_pay_uv' => $info->pay_uv,
  134. // 新增用户在{$date}vip充值支付人数
  135. 'new_user_vip_pay_uv' => $info->vip_pay_uv,
  136. // 新增用户在{$date}普通充值支付人数
  137. 'new_user_common_pay_uv' => $info->vip_pay_uv,
  138. ];
  139. } else {
  140. return null;
  141. }
  142. }
  143. public function promotionDayCharge($promotionId, $date) {
  144. $info = DB::table('orders')
  145. ->where('promotion_id', $promotionId)
  146. ->whereBetween('created_at', [$date, $date. ' 23:59:59'])
  147. ->where('ranse_created_at', '>', '2000-01-01')
  148. ->select(
  149. // 未支付金额
  150. DB::raw("sum(if(status = 'unpaid', price, 0)) as unpay_money"),
  151. // 未支付笔数
  152. DB::raw("sum(if(status = 'unpaid', 1, 0)) as unpay_count"),
  153. // 总金额
  154. DB::raw("sum(price) as total_money"),
  155. // 总笔数
  156. DB::raw("count(id) as total_count"),
  157. // 普通未支付笔数
  158. DB::raw("sum(if(status='unpaid' and order_type in ('coin', 'first_coin'), 1, 0)) as common_unpay_count"),
  159. // 普通总笔数
  160. DB::raw("sum(if(order_type in ('coin', 'first_coin'), 1, 0)) as common_count"),
  161. // 普通支付金额
  162. DB::raw("sum(if(order_type in ('coin', 'first_coin') and status <> 'unpaid', price, 0)) as common_pay_money"),
  163. // NOTE!!!,uid, ranse_created_at 唯一确定一个用户
  164. // 累计充值人数
  165. DB::raw("count(distinct if(status <> 'unpaid', concat(uid, ranse_created_at), null)) as pay_uv"),
  166. // 普通支付人数
  167. DB::raw("count(distinct if(order_type in ('coin', 'first_coin') and status <> 'unpaid', concat(uid, ranse_created_at), null)) as common_pay_uv"),
  168. // vip支付人数
  169. DB::raw("count(distinct if(order_type not in ('coin', 'first_coin') and status <> 'unpaid', concat(uid, ranse_created_at), null)) as vip_pay_uv"),
  170. // vip未支付笔数
  171. DB::raw("sum(if(order_type not in ('coin', 'first_coin') and status = 'unpaid', 1, 0)) as vip_unpay_count"),
  172. )->first();
  173. if($info) {
  174. return [
  175. // 支付金额
  176. 'pay_money' => bcsub($info->total_money, $info->unpay_money, 2),
  177. // 支付笔数
  178. 'pay_count' => $info->total_count - $info->unpay_count,
  179. /**
  180. * -----普通充值--------
  181. */
  182. // 支付金额
  183. 'common_pay_money' => $info->common_pay_money,
  184. // 支付人数
  185. 'common_pay_uv' => $info->common_pay_uv,
  186. // 支付笔数
  187. 'common_pay_count' => $info->common_count - $info->common_unpay_count,
  188. // 未支付笔数
  189. 'common_unpay_count' => $info->common_unpay_count,
  190. /**
  191. * ----会员充值------
  192. */
  193. // 支付金额
  194. 'vip_pay_money' => bcsub(bcsub($info->total_money, $info->unpay_money, 2), $info->common_pay_money, 2),
  195. // 支付人数
  196. 'vip_pay_uv' => $info->vip_pay_uv,
  197. // 支付笔数
  198. 'vip_pay_count' => $info->total_count - $info->unpay_count - ($info->common_count - $info->common_unpay_count),
  199. // 未支付笔数
  200. 'vip_unpay_count' => $info->vip_unpay_count,
  201. ];
  202. } else {
  203. return null;
  204. }
  205. }
  206. }