UserStatisticsService.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. *
  4. * @file:UserStatisticsService.php
  5. * @Date: 2023/6/20
  6. * @Time: 09:31
  7. */
  8. namespace Modules\Statistic\Services;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Facades\Redis;
  11. use Modules\Common\Models\TjOptimizerDayNewUser;
  12. use Modules\Common\Services\BaseService;
  13. class UserStatisticsService extends BaseService
  14. {
  15. // key 日期:
  16. protected const PROMOTION_STATISTIC_RECORD_REDIS_KEY = 'statistic:miniprogram:users_recode:%s';
  17. protected const NEW_USER_NUM = 'new_user_num_%s'; // 当日新增用户数
  18. protected const NEW_USER_RECHARGE_NUM = "new_user_recharge_num_%s"; // 当日新增户充值人数
  19. protected const NEW_USER_RECHARGE_TOTAL = "new_user_recharge_total_%s"; // 当日新增户充值金额
  20. protected const RANSE_NEW_USER_COUNT = "promotion:newUserCount:%s"; // 推广链接新用户统计
  21. /**
  22. *
  23. * name: getTodayData
  24. * @param int $accountId 账号id
  25. * @param int $type 账号类型 1 其他 2 投放公司 3 优化师
  26. * @param int $minId 小程序id
  27. * date 2023/06/20 10:20
  28. * @return array
  29. */
  30. public static function getTodayData($accountId, $type = 1,$minId=0)
  31. {
  32. $date = date("Y-m-d");
  33. $date = "2023-06-25";
  34. $start = $date. " 00:00:00";
  35. $end = $date . " 23:59:59";
  36. $where = [];
  37. if ($minId > 0){
  38. $where['miniprogram_id'] = $minId;
  39. }
  40. if ($type == 2){
  41. $where['puser_id'] = $accountId;
  42. }else if($type ==3){
  43. $where['user_id'] = $accountId;
  44. }
  45. $new_user_num = DB::table('user_ranse_record_all')->where($where)->where('date', $date)->count(); // 新增用户人数
  46. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  47. ->where($where)
  48. ->whereBetween("created_at", [$start, $end])
  49. ->whereBetween('ranse_created_at', [$start, $end])
  50. ->select(
  51. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  52. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  53. )->first();
  54. $new_user_recharge_total = $info->recharge_total ?: 0; // 新增用户充值总额
  55. $new_user_recharge_num = $info->recharge_num ?: 0; // 新增用户充值人数
  56. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  57. ->where($where)
  58. ->whereBetween("created_at", [$start, $end])
  59. ->whereBetween('ranse_created_at', [$start, $end])
  60. ->whereIn('order_type', ["COIN", "FIRST_COIN"])
  61. ->select(
  62. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  63. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  64. )->first(); // 普通充值金额
  65. $recharge_coin_total = $info->recharge_total ?: 0; // 新增用户普通充值总额
  66. $recharge_coin_num = $info->recharge_num ?: 0; // 新增用户普通充值总额
  67. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  68. ->where($where)
  69. ->whereBetween("created_at", [$start, $end])
  70. ->whereBetween('ranse_created_at', [$start, $end])
  71. ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])
  72. ->select(
  73. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  74. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  75. )->first(); // 会员充值金额
  76. $recharge_vip_total = $info->recharge_total ?: 0; // 新增用户会员充值总额
  77. $recharge_vip_num = $info->recharge_num ?: 0; // 新增用户会员充值总额
  78. $data = [
  79. 'date' => $date,
  80. 'new_user_recharge_total' => $new_user_recharge_total ?: 0,
  81. 'new_user_recharge_num' => $new_user_recharge_num ?: 0,
  82. 'new_user_num' => $new_user_num ?: 0,
  83. 'recharge_coin_total' => $recharge_coin_total ?: 0,
  84. 'recharge_coin_num' => $recharge_coin_num ?: 0,
  85. 'recharge_vip_total' => $recharge_vip_total ?: 0,
  86. 'recharge_vip_num' => $recharge_vip_num ?: 0,
  87. ];
  88. if ($new_user_num > 0 && $new_user_recharge_num > 0) {
  89. $data['recharge_rate'] = sprintf("%.2f%s", ($new_user_recharge_num / $new_user_num) * 100, "%");
  90. } else {
  91. $data['recharge_rate'] = 0;
  92. $data['recharge_mean'] = 0;
  93. }
  94. if ($new_user_recharge_total > 0 || $new_user_recharge_num > 0) {
  95. $data['recharge_mean'] = sprintf('%.2f%s', ($new_user_recharge_total / $new_user_recharge_num), "%");
  96. } else {
  97. $data['recharge_mean'] = 0;
  98. }
  99. return $data;
  100. }
  101. /**
  102. * 获取redis值
  103. * name: getValue
  104. * @param $key
  105. * @param $field
  106. * @return mixed
  107. * date 2023/06/25 15:57
  108. */
  109. protected static function getValue($key, $field)
  110. {
  111. return Redis::hget($key, $field);
  112. }
  113. /**
  114. *
  115. * name: getTodayData
  116. * @param int $accountId 账号id
  117. * @param int $type 账号类型 1 其他 2 投放公司 3 优化师
  118. * date 2023/06/20 10:20
  119. * @return array
  120. */
  121. public static function getTodayHomeData(mixed $accountId, int $type)
  122. {
  123. $date = date("Y-m-d");
  124. $start = date("Y-m-d") . " 00:00:00";
  125. $end = date("Y-m-d") . " 23:59:59";
  126. if ($type == 1) {
  127. $new_user_num = DB::table('user_ranse_record_all')->where('date', $date)->count(); // 新增用户人数
  128. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  129. ->whereBetween("created_at", [$start, $end])
  130. ->whereBetween('ranse_created_at', [$start, $end])
  131. ->select(
  132. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  133. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  134. )->first();
  135. $new_user_recharge_total = $info->recharge_total ?: 0; // 新增用户充值总额
  136. $new_user_recharge_num = $info->recharge_num ?: 0; // 新增用户充值人数
  137. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  138. ->whereBetween("created_at", [$start, $end])
  139. ->whereBetween('ranse_created_at', [$start, $end])
  140. ->whereIn('order_type', ["COIN", "FIRST_COIN"])
  141. ->select(
  142. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  143. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  144. )->first(); // 普通充值金额
  145. $new_user_recharge_coin_total = $info->recharge_total ?: 0; // 新增用户普通充值总额
  146. $new_user_recharge_coin_num = $info->recharge_num ?: 0; // 新增用户普通充值总额
  147. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  148. ->whereBetween("created_at", [$start, $end])
  149. ->whereBetween('ranse_created_at', [$start, $end])
  150. ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])
  151. ->select(
  152. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  153. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  154. )->first(); // 会员充值金额
  155. $new_user_recharge_vip_total = $info->recharge_total ?: 0; // 新增用户会员充值总额
  156. $new_user_recharge_vip_num = $info->recharge_num ?: 0; // 新增用户会员充值总额
  157. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  158. ->whereBetween("created_at", [$start, $end])
  159. ->select(
  160. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  161. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  162. )->first();
  163. $recharge_total = $info->recharge_total ?: 0; // 充值金额
  164. // 充值笔数
  165. $recharge_num = DB::table('orders')->where('status', "<>", 'UNPAID')
  166. ->whereBetween("created_at", [$start, $end])->count();
  167. $recharge_coin_total = DB::table('orders')->where('status', "<>", 'UNPAID')
  168. ->whereBetween("created_at", [$start, $end])
  169. ->whereIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 普通充值金额
  170. $recharge_vip_total = DB::table('orders')->where('status', "<>", 'UNPAID')
  171. ->whereBetween("created_at", [$start, $end])
  172. ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 会员充值金额
  173. } else {
  174. $key = sprintf(self::PROMOTION_STATISTIC_RECORD_REDIS_KEY, $date);
  175. $new_user_recharge_total = self::getValue($key, sprintf(self::NEW_USER_RECHARGE_TOTAL, $accountId)); // 当日新增用户充值总额
  176. $new_user_recharge_num = self::getValue($key, sprintf(self::NEW_USER_RECHARGE_NUM, $accountId)); // 当日新增用户充值人数
  177. $new_user_num = self::getValue($key, sprintf(self::NEW_USER_NUM, $accountId)); // 当日新增用户人数
  178. if ($type == 2) {
  179. $where = ['puser_id' => $accountId];
  180. } else {
  181. $where = ['user_id' => $accountId];
  182. }
  183. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  184. ->where($where)
  185. ->whereBetween("created_at", [$start, $end])
  186. ->whereBetween('ranse_created_at', [$start, $end])
  187. ->whereIn('order_type', ["COIN", "FIRST_COIN"])->select(
  188. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  189. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  190. )->first(); // 普通充值金额
  191. $new_user_recharge_coin_total = $info->recharge_total ?: 0; // 新增用户普通充值总额
  192. $new_user_recharge_coin_num = $info->recharge_num ?: 0; // 新增用户普通充值总额
  193. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  194. ->where($where)
  195. ->whereBetween("created_at", [$start, $end])
  196. ->whereBetween('ranse_created_at', [$start, $end])
  197. ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])
  198. ->select(
  199. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  200. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  201. )->first(); // 会员充值金额
  202. $new_user_recharge_vip_total = $info->recharge_total ?: 0; // 新增用户会员充值总额
  203. $new_user_recharge_vip_num = $info->recharge_num ?: 0; // 新增用户会员充值总额
  204. $info = DB::table('orders')->where('status', "<>", 'UNPAID')
  205. ->whereBetween("created_at", [$start, $end])
  206. ->where($where)
  207. ->select(
  208. DB::raw("sum(if(status = 'unpaid', 0, price)) as recharge_total"), // 单日新增用户充值金额
  209. DB::raw("count(DISTINCT ranse_created_at,uid) as recharge_num") // 当日新增用户充值人数
  210. )->first();
  211. $recharge_total = $info->recharge_total ?: 0; // 充值人数
  212. $recharge_num = DB::table('orders')->where('status', "<>", 'UNPAID')
  213. ->whereBetween("created_at", [$start, $end])
  214. ->where($where)->count();
  215. $recharge_coin_total = DB::table('orders')->where('status', "<>", 'UNPAID')
  216. ->where($where)
  217. ->whereBetween("created_at", [$start, $end])
  218. ->whereIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 普通充值金额
  219. $recharge_vip_total = DB::table('orders')->where('status', "<>", 'UNPAID')
  220. ->where($where)
  221. ->whereBetween("created_at", [$start, $end])
  222. ->whereNotIn('order_type', ["COIN", "FIRST_COIN"])->sum('price'); // 会员充值金额
  223. }
  224. $data = [
  225. 'new_user_num' => $new_user_num, // 新增用户数
  226. 'new_user_recharge_num' => $new_user_recharge_num, // 新增用户充值人数
  227. 'new_user_recharge_coin_num' => $new_user_recharge_coin_num, // 新增用户普通充值人数
  228. 'new_user_recharge_vip_num' => $new_user_recharge_vip_num, // 新增用户vip充值人数
  229. 'new_user_recharge_total' => $new_user_recharge_total, // 新增用户充值金额
  230. 'new_user_recharge_vip_total' => $new_user_recharge_vip_total, // 新增用户普通充值金额
  231. 'new_user_recharge_coin_total' => $new_user_recharge_coin_total, // 新增用户vip充值金额
  232. 'recharge_total' => $recharge_total, // 充值金额
  233. 'recharge_coin_totall' => $recharge_coin_total, // 普通充值金额
  234. 'recharge_vip_total' => $recharge_vip_total, // VIP 充值金额
  235. 'recharge_num' => $recharge_num, // 充值笔数
  236. ];
  237. // 新增用户充值率
  238. $data['new_user_recharge_rate'] = $data['new_user_num'] > 0 && $data['new_user_recharge_num'] > 0 ? sprintf("%.2f%s",$data['new_user_recharge_num']/$data['new_user_num'],"%") : 0;
  239. // 新增用户人均充值
  240. $data['new_user_mean'] = $data['new_user_num'] > 0 && $data['new_user_recharge_total'] > 0 ? sprintf("%.2f",$data['new_user_recharge_total']/$data['new_user_num']) : 0;
  241. $data['recharge_mean'] = $data['recharge_total'] > 0 && $data['recharge_num'] > 0 ? sprintf("%.2f",$data['recharge_total']/$data['recharge_num'],"%") : 0; // 新增用户人均充值
  242. return $data;
  243. }
  244. /**
  245. * 保存redis的值
  246. * name: setValue
  247. * @param $key
  248. * @param $field
  249. * @param $value
  250. * date 2023/06/25 15:57
  251. */
  252. protected static function setValue($key, $field, $value)
  253. {
  254. Redis::hset($key, $field, $value);
  255. }
  256. /**
  257. *
  258. * name: getTodayData
  259. * @param int $accountId 账号id
  260. * @param mixed $type 账号类型 1 其他 2 投放公司 3 优化师
  261. * @param mixed $miniProgramId 小程序id
  262. */
  263. public static function historyStats(int $accountId, $type,$miniProgramId)
  264. {
  265. $month = self::getStaticsData($accountId, date('Y-m-01'), date('Y-m-d', strtotime('yesterday')), $type,$miniProgramId);
  266. $lastMonth = self::getStaticsData($accountId, date('Y-m-01', strtotime(date('Y-m-01')) - 10), date('Y-m-d', strtotime(date('Y-m-01')) - 10), $type,$miniProgramId);
  267. $history = self::getHistoryData($accountId, $type,$miniProgramId);
  268. return ['month' => $month, 'lastMonth' => $lastMonth, 'history' => $history];
  269. }
  270. /**
  271. * 历史汇总
  272. * name: getMonthData
  273. * @param int $accountId 账号
  274. * @param mixed $type 角色类型 账号类型 1 其他 2 投放公司 3 优化师
  275. * @param mixed $minId 小程序id
  276. * date 2023/06/27 11:19
  277. */
  278. protected static function getHistoryData($accountId, $type, $minId = 0)
  279. {
  280. $date = date('Y-m-d', strtotime('yesterday'));
  281. $sql = TjOptimizerDayNewUser::where('date', $date);
  282. if ($type == 2) {
  283. $sql->where('puser_id', $accountId);
  284. } elseif ($type == 3) {
  285. $sql->where('puser_id', $accountId);
  286. }
  287. if ($minId) {
  288. $sql->where('miniprogram_id', $minId);
  289. }
  290. $info = $sql->select(
  291. DB::raw("sum(recharge_amount_total) as recharge_amount_total"), // 总充金额
  292. DB::raw("sum(new_user_total) as new_user_total"), // 总充金额
  293. DB::raw("sum(recharge_user_total) as recharge_user_total"), // 累计充值人数
  294. )->first();
  295. return [
  296. 'recharge_amount_total' => $info->recharge_amount_total ?: 0,
  297. 'new_user_total' => $info->new_user_total ?: 0,
  298. 'recharge_user_total' => $info->recharge_user_total ?: 0,
  299. ];
  300. }
  301. /**
  302. * 日期范围的统计
  303. * name: getMonthData
  304. * @param int $accountId 账号
  305. * @param mixed $type 角色类型 账号类型 1 其他 2 投放公司 3 优化师
  306. * @param mixed $minId 小程序id
  307. * date 2023/06/27 11:19
  308. */
  309. private static function getStaticsData($accountId, $start, $end, $type, $minId = 0)
  310. {
  311. $sql = TjOptimizerDayNewUser::where('date', '>=', $start)->where("date", "<=", $end);
  312. if ($type == 2) {
  313. $sql->where('puser_id', $accountId);
  314. } elseif ($type == 3) {
  315. $sql->where('puser_id', $accountId);
  316. }
  317. if ($minId) {
  318. $sql->where('miniprogram_id', $minId);
  319. }
  320. return self::handleStaticData($sql);
  321. }
  322. /**
  323. * 统计数据处理
  324. * name: handelStaticData
  325. * @param $sql
  326. * @return array
  327. * date 2023/06/27 14:51
  328. */
  329. protected static function handleStaticData($sql): array
  330. {
  331. $info = $sql->select(
  332. DB::raw("sum(new_user_recharge_total) as new_user_recharge_total"), // 充值人数
  333. DB::raw("sum(new_user_num) as new_user_num"), // 新增用户人数
  334. DB::raw("sum(new_user_recharge_num) as new_user_recharge_num"), // 充值人数
  335. DB::raw("sum(new_user_recharge_vip_num) as new_user_recharge_vip_num"), // VIP充值人数
  336. DB::raw("sum(new_user_recharge_coin_num) as new_user_recharge_coin_num") // 普通充值人数
  337. )->first();
  338. return [
  339. 'new_user_recharge_total' => $info->new_user_recharge_total ?: 0,
  340. 'new_user_num' => $info->new_user_num ?: 0,
  341. 'new_user_recharge_num' => $info->new_user_recharge_num ?: 0,
  342. 'new_user_recharge_vip_num' => $info->new_user_recharge_vip_num ?: 0,
  343. 'new_user_recharge_coin_num' => $info->new_user_recharge_coin_num ?: 0,
  344. ];
  345. }
  346. /**
  347. * 统计列表
  348. */
  349. public static function list($param)
  350. {
  351. $sql = self::getQuerySql($param)->select("tj_optimizer_day_new_users.*", 'users.username')->orderBy('date', 'desc')->orderBy('id', 'desc');
  352. $isAll = getProp($param, 'is_all');
  353. if ($isAll) {
  354. $list = $sql->get();
  355. } else {
  356. $list = $sql->paginate(getProp($param, 'limit', 15));
  357. }
  358. if ($list->isEmpty()) {
  359. return $list;
  360. }
  361. $companyIds = $list->pluck('puser_id')->unique()->toArray();
  362. $companys = DB::table('users')->whereIn('id', $companyIds)->get();
  363. foreach ($list as $value) {
  364. // 充值率
  365. $value->recharge_rate = $value->new_user_recharge_num > 0 && $value->new_user_num > 0 ? sprintf("%.2f%s", $value->new_user_recharge_num / $value->new_user_num, "%") : 0;
  366. // 人均充值
  367. $value->recharge_mean = $value->new_user_recharge_num > 0 && $value->new_user_recharge_total > 0 ? sprintf("%.2f%s", $value->new_user_recharge_total / $value->new_user_recharge_num, "%") : 0;
  368. $value->company_name = $companys->where('id', $value->puser_id)->value('username');
  369. }
  370. return $list;
  371. }
  372. // 列表数据统计
  373. public static function listStatistics($param): array
  374. {
  375. $sql = self::getQuerySql($param);
  376. return self::handleStaticData($sql);
  377. }
  378. private static function getQuerySql(array $param)
  379. {
  380. $sql = TjOptimizerDayNewUser::query()->leftJoin('users', 'users.id', "=", 'tj_optimizer_day_new_users.user_id');
  381. if (getProp($param, 'start_at')) {
  382. $sql->where('tj_optimizer_day_new_users.date', ">=", $param['start_at']);
  383. }
  384. if (getProp($param, 'end_at')) {
  385. $sql->where('tj_optimizer_day_new_users.date', "<=", $param['end_at']);
  386. }
  387. if (getProp($param, 'user_id')) {
  388. $sql->where('tj_optimizer_day_new_users.user_id', $param['user_id']);
  389. }
  390. if (getProp($param, 'puser_id')) {
  391. $sql->where('tj_optimizer_day_new_users.puser_id', $param['puser_id']);
  392. }
  393. if (getProp($param, 'miniprogram_id')) {
  394. $sql->where('tj_optimizer_day_new_users.miniprogram_id', $param['miniprogram_id']);
  395. }
  396. return $sql;
  397. }
  398. }