StatisticalUserCommand.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <?php
  2. namespace App\Console\Commands\Dwbs;
  3. use App\Repositories\Enums\Dwbs\DayTypeEnum;
  4. use App\Repositories\Enums\ModelStatusEnum;
  5. use App\Repositories\Models\Base\Setting;
  6. use App\Repositories\Models\Base\User;
  7. use App\Repositories\Models\Dwbs\Ranking;
  8. use App\Repositories\Models\Dwbs\UserJifen;
  9. use App\Repositories\Models\Dwbs\UserXuefen;
  10. use Carbon\Carbon;
  11. use Illuminate\Console\Command;
  12. use Illuminate\Support\Facades\Log;
  13. /**
  14. * 统计用户数据
  15. * @package Prettus\Repository\Generators\Commands
  16. * @author Anderson Andrade <contato@andersonandra.de>
  17. */
  18. class StatisticalUserCommand extends Command
  19. {
  20. /**
  21. * The name of command.
  22. *
  23. * @var string
  24. */
  25. protected $signature = 'statistical:user {date?}';
  26. /**
  27. * The description of command.
  28. *
  29. * @var string
  30. */
  31. protected $description = '统计汇总数据';
  32. /**
  33. * The type of class being generated.
  34. *
  35. * @var string
  36. */
  37. protected $type = 'permission';
  38. /**
  39. * Execute the command.
  40. *
  41. * @return void
  42. * @see fire()
  43. */
  44. public function handle()
  45. {
  46. $day = $this->argument('date');
  47. $now = Carbon::now()->toDateString();
  48. if (!$day) {
  49. $day = Carbon::yesterday()->toDateString();
  50. } else {
  51. $now = Carbon::parse($day)->toDateString();
  52. $day = Carbon::parse($day)->subDay()->toDateString();
  53. }
  54. try {
  55. //1.汇总天的数据
  56. $this->line("天:{$day}");
  57. $this->day($day);
  58. //2.汇周的数据
  59. $firstDay = Carbon::parse($now)->startOfWeek();
  60. if (Carbon::parse($now)->isSameDay($firstDay)) {
  61. $sDay = Carbon::parse($day)->startOfWeek()->toDateString();
  62. $eDay = Carbon::parse($day)->endOfWeek()->toDateString();
  63. $this->line("周:{$sDay}--{$eDay}");
  64. $this->zhouqitongji($sDay, $eDay, DayTypeEnum::week, Carbon::parse($sDay)->subDays(7)->toDateString());
  65. }
  66. //3.汇月的数据
  67. $firstDay = Carbon::parse($now)->startOfMonth();
  68. if (Carbon::parse($now)->isSameDay($firstDay)) {
  69. $sDay = Carbon::parse($day)->startOfMonth()->toDateString();
  70. $eDay = Carbon::parse($day)->endOfMonth()->toDateString();
  71. $this->line("月:{$sDay}--{$eDay}");
  72. $this->zhouqitongji($sDay, $eDay, DayTypeEnum::month, Carbon::parse($sDay)->subMonth()->toDateString());
  73. }
  74. //4.汇季度的数据
  75. $firstDay = Carbon::parse($now)->startOfQuarter();
  76. if (Carbon::parse($now)->isSameDay($firstDay)) {
  77. $sDay = Carbon::parse($day)->startOfQuarter()->toDateString();
  78. $eDay = Carbon::parse($day)->endOfQuarter()->toDateString();
  79. $this->line("季:{$sDay}--{$eDay}");
  80. $this->zhouqitongji($sDay, $eDay, DayTypeEnum::quarter, Carbon::parse($sDay)->subQuarter()->toDateString());
  81. }
  82. //5.汇年的数据
  83. $firstDay = Carbon::parse($now)->startOfYear();
  84. if (Carbon::parse($now)->isSameDay($firstDay)) {
  85. $sDay = Carbon::parse($day)->startOfYear()->toDateString();
  86. $eDay = Carbon::parse($day)->endOfYear()->toDateString();
  87. $this->line("年:{$sDay}--{$eDay}");
  88. $this->zhouqitongji($sDay, $eDay, DayTypeEnum::year, Carbon::parse($sDay)->subYear()->toDateString());
  89. }
  90. } catch (\Exception $exception) {
  91. log_record('每天汇总异常', compact('day', 'now'));
  92. Log::error($exception);
  93. }
  94. }
  95. /**
  96. * 周统计
  97. * @param $sDay
  98. * @param $eDay
  99. * @return true
  100. */
  101. public function zhouqitongji($sDay, $eDay, $day_type, $perv_date)
  102. {
  103. $isOpenGroup = (bool)Setting::byCodeGetSetting('h5_paihangbang_is_group_user');
  104. User::query()->where('xuefen', '>', 0)->chunkById(100, function ($users) use ($sDay, $eDay, $day_type, $perv_date, $isOpenGroup) {
  105. foreach ($users as $user) {
  106. $user_id = $user['id'];
  107. $group_id = $user['group_id'];
  108. $day_group_id = 0;
  109. if ($isOpenGroup) $day_group_id = $group_id;
  110. $ranking = Ranking::query()->where([
  111. 'day_type' => DayTypeEnum::day,
  112. 'day' => $eDay,
  113. 'user_id' => $user_id
  114. ])->first();
  115. if (!$ranking) {
  116. $xuefen = 0;
  117. $last_update_time = Carbon::now();
  118. $jifen = 0;
  119. $paiming = 0;
  120. continue;
  121. } else {
  122. $xuefen = $ranking->xuefen;
  123. $last_update_time = $ranking->last_update_time;
  124. $jifen = $ranking->jifen;
  125. $paiming = $ranking->paiming;
  126. }
  127. $yesterday_mingci = Ranking::query()->where('day_type', $day_type)->whereDate('day', $perv_date)->value('paiming') ?? 0;
  128. $is_inc_paiming = 0;
  129. if ($yesterday_mingci < $paiming) {
  130. $is_inc_paiming = -1;
  131. } elseif ($yesterday_mingci > $paiming) {
  132. $is_inc_paiming = 1;
  133. }
  134. if (!$yesterday_mingci) {
  135. $is_inc_paiming = 1;
  136. }
  137. $day_xuefen = Ranking::query()->where('user_id', $user_id)->whereDate('day', '<=', $eDay)->whereDate('day', '>=', $sDay)->where('status', ModelStatusEnum::OK)->sum('day_xuefen');
  138. $day_jifen = Ranking::query()->where('user_id', $user_id)->whereDate('day', '<=', $eDay)->whereDate('day', '>=', $sDay)->where('status', ModelStatusEnum::OK)->sum('day_jifen');
  139. Ranking::query()->updateOrCreate([
  140. 'day_type' => $day_type,
  141. 'day' => $sDay,
  142. 'user_id' => $user_id,
  143. ], [
  144. 'group_id' => $group_id,
  145. 'day_group_id' => $day_group_id,
  146. 'status' => ModelStatusEnum::OK,
  147. 'day_xuefen' => $day_xuefen,
  148. 'day_jifen' => $day_jifen,
  149. 'xuefen' => $xuefen,
  150. 'jifen' => $jifen,
  151. 'paiming' => $paiming,
  152. 'is_inc_paiming' => $is_inc_paiming,
  153. 'last_update_time' => $last_update_time,
  154. 'is_xueba' => 0,
  155. ]);
  156. }
  157. });
  158. //学霸
  159. if ($isOpenGroup) {
  160. foreach (User::GroupMaps as $map) {
  161. $ranking = Ranking::query()->where([
  162. 'day_type' => $day_type,
  163. 'day' => $sDay,
  164. 'status' => ModelStatusEnum::OK,
  165. 'group_id' => $map['id'],
  166. ])->orderByDesc('xuefen')->first();
  167. if ($ranking) {
  168. $ranking->is_xueba = 1;
  169. $ranking->save();
  170. }
  171. }
  172. } else {
  173. $ranking = Ranking::query()->where([
  174. 'day_type' => $day_type,
  175. 'day' => $sDay,
  176. 'status' => ModelStatusEnum::OK,
  177. ])->orderByDesc('xuefen')->first();
  178. if ($ranking) {
  179. $ranking->is_xueba = 1;
  180. $ranking->save();
  181. }
  182. }
  183. return true;
  184. }
  185. /**
  186. * 统计天的数据
  187. * @param $day
  188. * @return true
  189. */
  190. public function day($day)
  191. {
  192. $isOpenGroup = (bool)Setting::byCodeGetSetting('h5_paihangbang_is_group_user');
  193. User::query()->where('xuefen', '>', 0)->chunkById(1000, function ($users) use ($day, $isOpenGroup) {
  194. foreach ($users as $user) {
  195. $user_id = $user['id'];
  196. $group_id = $user['group_id'];
  197. $day_group_id = 0;
  198. if ($isOpenGroup) $day_group_id = $group_id;
  199. $lastXuefen = UserXuefen::query()->where('user_id', $user_id)->whereDate('day', '<=', $day)->where('status', ModelStatusEnum::OK)->orderByDesc('id')->select(['user_xuefen', 'created_at'])->first();
  200. if (!$lastXuefen) {
  201. continue;
  202. }
  203. $xuefen = $lastXuefen->user_xuefen;
  204. $last_update_time = $lastXuefen->created_at;
  205. $jifen = UserJifen::query()->where('user_id', $user_id)->whereDate('day', '<=', $day)->where('status', ModelStatusEnum::OK)->orderByDesc('id')->value('user_jifen') ?? 0;
  206. $paiming = 0;
  207. $is_inc_paiming = 0;
  208. if ((int)$user->xuefen === (int)$xuefen) {
  209. $paiming = $user->mingci;
  210. if ($user->yesterday_mingci < $paiming) {
  211. $is_inc_paiming = -1;
  212. } elseif ($user->yesterday_mingci > $paiming) {
  213. $is_inc_paiming = 1;
  214. }
  215. if (!$user->yesterday_mingci) {
  216. $is_inc_paiming = 1;
  217. }
  218. $user->yesterday_mingci = $paiming;
  219. $user->save();
  220. }
  221. $day_xuefen = UserXuefen::query()->where('user_id', $user_id)->whereDate('day', $day)->where('status', ModelStatusEnum::OK)->sum('xuefen');
  222. $day_jifen = UserJifen::query()->where('user_id', $user_id)->whereDate('day', $day)->where('status', ModelStatusEnum::OK)->sum('jifen');
  223. Ranking::query()->updateOrCreate([
  224. 'day_type' => DayTypeEnum::day,
  225. 'day' => $day,
  226. 'user_id' => $user_id,
  227. ], [
  228. 'group_id' => $group_id,
  229. 'day_group_id' => $day_group_id,
  230. 'status' => ModelStatusEnum::OK,
  231. 'day_xuefen' => $day_xuefen,
  232. 'day_jifen' => $day_jifen,
  233. 'xuefen' => $xuefen,
  234. 'jifen' => $jifen,
  235. 'paiming' => $paiming,
  236. 'is_inc_paiming' => $is_inc_paiming,
  237. 'last_update_time' => $last_update_time,
  238. 'is_xueba' => 0,
  239. ]);
  240. }
  241. });
  242. //补充排名
  243. Ranking::query()->where([
  244. 'day_type' => DayTypeEnum::day,
  245. 'day' => $day,
  246. 'status' => ModelStatusEnum::OK,
  247. 'paiming' => 0
  248. ])->chunkById(1000, function ($ranks) use ($day, $isOpenGroup) {
  249. foreach ($ranks as $ranking) {
  250. $meXuefen = $ranking->xuefen;
  251. $last_update_time = $ranking->last_update_time;
  252. $day_group_id = $ranking->day_group_id;
  253. $paiming = Ranking::query()->where([
  254. 'day_type' => DayTypeEnum::day,
  255. 'day' => $day,
  256. 'status' => ModelStatusEnum::OK,
  257. ])->when($isOpenGroup, function ($query) use ($day_group_id) {
  258. return $query->where('group_id', $day_group_id);
  259. })->where(function ($query) use ($meXuefen, $last_update_time) {
  260. return $query->orWhere('xuefen', '>', $meXuefen)->orWhere(function ($q) use ($last_update_time, $meXuefen) {
  261. return $q->where('xuefen', '=', $meXuefen)->where('last_update_time', '<', $last_update_time);
  262. });
  263. })->where('status', ModelStatusEnum::OK)->count();
  264. $paiming += 1;
  265. $ranking->paiming = $paiming;
  266. $user = User::query()->where('id', $ranking->user_id)->select(['id', 'xuefen', 'jifen', 'last_update_time', 'yesterday_mingci'])->first();
  267. $is_inc_paiming = 0;
  268. if ($user->yesterday_mingci < $paiming) {
  269. $is_inc_paiming = -1;
  270. } elseif ($user->yesterday_mingci > $paiming) {
  271. $is_inc_paiming = 1;
  272. }
  273. if (!$user->yesterday_mingci) {
  274. $is_inc_paiming = 1;
  275. }
  276. $ranking->is_inc_paiming = $is_inc_paiming;
  277. $user->yesterday_mingci = $paiming;
  278. $user->save();
  279. $ranking->save();
  280. }
  281. });
  282. //学霸
  283. if ($isOpenGroup) {
  284. foreach (User::GroupMaps as $map) {
  285. $ranking = Ranking::query()->where([
  286. 'day_type' => DayTypeEnum::day,
  287. 'day' => $day,
  288. 'status' => ModelStatusEnum::OK,
  289. 'group_id' => $map['id'],
  290. ])->orderByDesc('xuefen')->first();
  291. if ($ranking) {
  292. $ranking->is_xueba = 1;
  293. $ranking->save();
  294. }
  295. }
  296. } else {
  297. $ranking = Ranking::query()->where([
  298. 'day_type' => DayTypeEnum::day,
  299. 'day' => $day,
  300. 'status' => ModelStatusEnum::OK,
  301. ])->orderByDesc('xuefen')->first();
  302. if ($ranking) {
  303. $ranking->is_xueba = 1;
  304. $ranking->save();
  305. }
  306. }
  307. return true;
  308. }
  309. }