RegisterHourlyStatsLogic.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <?php
  2. namespace App\Http\logic\api;
  3. use Illuminate\Support\Facades\DB;
  4. class RegisterHourlyStatsLogic extends BaseApiLogic
  5. {
  6. /**
  7. * 获取按小时分布的注册用户、首充付费人数统计
  8. * 新增付费人数:在指定日期注册的用户,在注册后24小时内有首充的用户
  9. *
  10. * @param string $date 日期 格式: Y-m-d
  11. * @param int $channel 渠道ID,默认102
  12. * @return array|false
  13. */
  14. public function getHourlyStats($date, $channel = 102)
  15. {
  16. try {
  17. // 验证日期格式
  18. if (!$this->validateDate($date)) {
  19. $this->error = 'Invalid date format. Please use Y-m-d format.';
  20. return false;
  21. }
  22. // 构建日期时间范围(当天00:00:00 到 23:59:59)
  23. $startDateTime = $date . ' 00:00:00';
  24. $endDateTime = $date . ' 23:59:59';
  25. // 查询注册数据 - 按小时分组统计,添加渠道筛选
  26. $registerStats = DB::connection('account')
  27. ->table('QPAccountsDB.dbo.AccountsInfo')
  28. ->select(
  29. DB::raw("DATEPART(HOUR, RegisterDate) as hour"),
  30. DB::raw("COUNT(*) as register_count")
  31. )
  32. ->where('Channel', $channel)
  33. ->whereBetween('RegisterDate', [$startDateTime, $endDateTime])
  34. ->groupBy(DB::raw("DATEPART(HOUR, RegisterDate)"))
  35. ->orderBy('hour')
  36. ->get();
  37. // 获取所有注册用户的ID和注册时间
  38. $registeredUsers = DB::connection('account')
  39. ->table('QPAccountsDB.dbo.AccountsInfo')
  40. ->select('UserID', DB::raw("DATEPART(HOUR, RegisterDate) as register_hour"), 'RegisterDate')
  41. ->where('Channel', $channel)
  42. ->whereBetween('RegisterDate', [$startDateTime, $endDateTime])
  43. ->get()
  44. ->keyBy('UserID');
  45. // 初始化结果数组(24小时)
  46. $result = [];
  47. for ($hour = 0; $hour < 24; $hour++) {
  48. $result[$hour] = [
  49. 'hour' => $hour,
  50. 'hour_display' => sprintf('%02d点', $hour),
  51. 'register_count' => 0,
  52. 'first_charge_count' => 0,
  53. 'charge_rate' => 0,
  54. ];
  55. }
  56. // 填充注册数据
  57. foreach ($registerStats as $stat) {
  58. $hour = (int)$stat->hour;
  59. $result[$hour]['register_count'] = (int)$stat->register_count;
  60. }
  61. // 查询首充数据:在注册后24小时内有首充的用户
  62. if ($registeredUsers->count() > 0) {
  63. $userIds = $registeredUsers->pluck('UserID')->toArray();
  64. // 查询这些用户在注册后24小时内的首充记录
  65. $firstChargeUsers = DB::connection('write')
  66. ->table('agent.dbo.order as o')
  67. ->leftJoin('QPAccountsDB.dbo.AccountsInfo as ai', 'o.user_id', '=', 'ai.UserID')
  68. ->select('o.user_id', 'o.finished_at', 'ai.RegisterDate')
  69. ->where('o.GiftsID', 301)
  70. ->where('o.pay_status', 1)
  71. ->whereNotNull('o.finished_at')
  72. ->whereIn('o.user_id', $userIds)
  73. ->get();
  74. // 按注册小时统计首充人数(首充时间必须在注册后24小时内)
  75. $chargeCountByHour = [];
  76. foreach ($firstChargeUsers as $charge) {
  77. $userId = $charge->user_id;
  78. if (!isset($registeredUsers[$userId])) {
  79. continue;
  80. }
  81. $registerDate = strtotime($registeredUsers[$userId]->RegisterDate);
  82. $chargeDate = strtotime($charge->finished_at);
  83. // 检查首充是否在注册后24小时内
  84. $hoursDiff = ($chargeDate - $registerDate) / 3600;
  85. if ($hoursDiff >= 0 && $hoursDiff <= 24) {
  86. $registerHour = (int)$registeredUsers[$userId]->register_hour;
  87. if (!isset($chargeCountByHour[$registerHour])) {
  88. $chargeCountByHour[$registerHour] = [];
  89. }
  90. // 使用数组去重,确保每个用户只计算一次
  91. if (!in_array($userId, $chargeCountByHour[$registerHour])) {
  92. $chargeCountByHour[$registerHour][] = $userId;
  93. }
  94. }
  95. }
  96. // 填充首充数据
  97. foreach ($chargeCountByHour as $hour => $userIds) {
  98. $result[$hour]['first_charge_count'] = count($userIds);
  99. }
  100. }
  101. // 计算付费率
  102. foreach ($result as &$row) {
  103. if ($row['register_count'] > 0) {
  104. $row['charge_rate'] = round(($row['first_charge_count'] / $row['register_count']) * 100, 2);
  105. }
  106. }
  107. // 添加日期和渠道信息
  108. foreach ($result as &$row) {
  109. $row['date'] = $date;
  110. $row['channel'] = $channel;
  111. }
  112. return array_values($result);
  113. } catch (\Exception $e) {
  114. $this->error = 'Database query error: ' . $e->getMessage();
  115. return false;
  116. }
  117. }
  118. /**
  119. * 验证日期格式
  120. *
  121. * @param string $date
  122. * @return bool
  123. */
  124. private function validateDate($date)
  125. {
  126. $d = \DateTime::createFromFormat('Y-m-d', $date);
  127. return $d && $d->format('Y-m-d') === $date;
  128. }
  129. }