NewOrderCountingRecordService.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. <?php
  2. namespace App\Services;
  3. use App\Logistic;
  4. use App\Order;
  5. use App\OrderCountingRecord;
  6. use App\Warehouse;
  7. use Carbon\Carbon;
  8. use Illuminate\Database\Eloquent\Builder;
  9. use Illuminate\Support\Arr;
  10. use Illuminate\Support\Collection;
  11. use Illuminate\Support\Facades\Cache;
  12. use App\Traits\ServiceAppAop;
  13. class NewOrderCountingRecordService
  14. {
  15. use ServiceAppAop;
  16. protected $modelClass = OrderCountingRecord::class;
  17. public function orderCountingRecordsFromCache($start, $end, $unit, $ownerIds)
  18. {
  19. $dataList = collect();
  20. if (count($ownerIds) == 1) return $this->orderCountingRecords($start, $end, $unit, $ownerIds);//当前用户只有一个货主权限,只需执行旧方法即可
  21. $queryCondition = $this->transfersToCondition($start, $end, $unit, $ownerIds);//根据条件获取查询条件
  22. $md5OwnerIds = md5(join(Arr::sortRecursive($ownerIds)));//将$ownerIds排序,保证md5加密后结果一致 将当前用户拥有的ownerIds进行md5加密
  23. foreach ($queryCondition['data'] as $dateStr => $ownerIds) {
  24. $key = 'new_order_counting_records_' . $dateStr . '_' . $md5OwnerIds . '_' . $queryCondition['unit'];
  25. $data = cache()->remember($key, $this->getTtl($dateStr, $unit), function () use ($dateStr, $unit, $ownerIds) {
  26. //如果缓存不存在,则将$dateStr作为查询条件,使用之前的接口查询改日的订单量统计结果,由于接口返回collect,去其中的第一个
  27. //因为查询条件仅为一天
  28. return $this->orderCountingRecords($dateStr, $dateStr, $unit, $ownerIds)->first();
  29. });
  30. $dataList->push($data);
  31. }
  32. return $dataList;
  33. }
  34. public function orderCountingRecords($start, $end, $unit, $ownerIds)
  35. {
  36. $orders = $this->get($start, $end, $unit, $ownerIds);
  37. $dataList = collect();
  38. $orders->groupBy('date_target')->sortKeys()->each(function ($items) use (&$dataList, $unit) {
  39. $counter = $items->reduce(function ($sum, $item) {
  40. return $sum + $item->amount;
  41. }, 0);
  42. $date_target = $items[0]->date_target;
  43. $dataList->push([
  44. 'counter' => $counter,
  45. 'date_target' => $date_target,
  46. ]);
  47. });
  48. return $dataList;
  49. }
  50. public function logisticsCountingRecords($start, $end, $ownerIds)
  51. {
  52. $key = 'logisticsCountingRecords_' . $start . '_' . $end . '_' . json_encode($ownerIds);
  53. return Cache::remember($key, config('cache.expirations.logisticsCountingRecords'), function () use ($start, $end, $ownerIds) {
  54. $dataList = collect();
  55. $resultOrders = $this->get($start, $end, '日', $ownerIds);
  56. $resultOrders->groupBy('logistic_id')->each(function ($item) use (&$dataList) {
  57. $counter = $item->reduce(function ($sum, $item) {
  58. return $sum + $item->amount;
  59. }, 0);
  60. $dataList->push([
  61. 'value' => $counter,
  62. 'logistic_id' => $item[0]->logistic_id,
  63. ]);
  64. });
  65. $map = [];
  66. $logistics = Logistic::query()->whereIn('id', data_get($dataList, '*.logistic_id'))->get();
  67. $logistics->each(function ($logistic) use (&$map) {
  68. $map[$logistic->id] = $logistic;
  69. });
  70. return $dataList->map(function (&$item) use ($map) {
  71. $logistic = $map[$item['logistic_id']] ?? '';
  72. $item['name'] = $logistic->name ?? '';
  73. return $item;
  74. });
  75. });
  76. }
  77. public function warehouseCountingRecords($start, $end, $ownerIds)
  78. {
  79. $key = 'warehouseCountingRecords_' . $start . '_' . $end . '_' . json_encode($ownerIds);
  80. return Cache::remember($key, config('cache.expirations.warehouseCountingRecords'), function () use ($start, $end, $ownerIds) {
  81. $dataList = collect();
  82. $resultOrders = $this->get($start, $end, '日', $ownerIds);
  83. $resultOrders->groupBy('warehouse_id')->each(function ($item) use (&$dataList) {
  84. $counter = $item->reduce(function ($sum, $item) {
  85. return $sum + $item->amount;
  86. }, 0);
  87. $warehouse = Warehouse::query()->find($item[0]->warehouse_id);
  88. $dataList->push([
  89. 'value' => $counter,
  90. 'warehouse_id' => $item[0]->warehouse_id,
  91. 'name' => $warehouse ? $warehouse->name : '仓库为空',
  92. 'code' => $warehouse ? $warehouse->code : 'NULL',
  93. ]);
  94. });
  95. return $dataList;
  96. });
  97. }
  98. public function get($start, $end, $unit, $ownerIds)
  99. {
  100. $queryCondition = $this->transfersToCondition($start, $end, $unit, $ownerIds);
  101. return $this->getOrderCountingRecords($queryCondition);
  102. }
  103. public function getFromCache($queryCondition): array
  104. {
  105. $lackingCondition = [];
  106. $orderCountingRecords_FromCache = collect();
  107. $lackingCondition['unit'] = $queryCondition['unit'];
  108. foreach ($queryCondition['data'] as $dateStr => $ownerIds) {
  109. foreach ($ownerIds as $ownerId) {
  110. $key = 'order_counting_records_' . $dateStr . '_' . $ownerId . '_' . $queryCondition['unit'];
  111. $items = cache()->get($key);
  112. if (empty($items)) {
  113. if (empty($lackingCondition['data'][$dateStr])) {
  114. $lackingCondition['data'][$dateStr] = [];
  115. }
  116. $lackingCondition['data'][$dateStr][] = $ownerId;
  117. } else {
  118. foreach ($items as $item) {
  119. $orderCountingRecords_FromCache->push($item);
  120. }
  121. }
  122. }
  123. }
  124. return [$orderCountingRecords_FromCache, $lackingCondition];
  125. }
  126. public function getFromMiddleTable($queryCondition): array
  127. {
  128. $orderSqlBuilder = OrderCountingRecord::query();
  129. $unit = $queryCondition['unit'];
  130. foreach ($queryCondition['data'] as $date => $owners) {
  131. $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) {
  132. $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit);
  133. });
  134. }
  135. $dataFromMiddleTable = $orderSqlBuilder->get();
  136. $this->insertIntoCache($dataFromMiddleTable, $unit);
  137. $queryCondition = $this->unQueryCondition($dataFromMiddleTable, $queryCondition);
  138. $orderCountingRecords_fromSelfTable = $dataFromMiddleTable;
  139. $lackingCondition = $queryCondition;
  140. return [$orderCountingRecords_fromSelfTable, $lackingCondition];
  141. }
  142. /**
  143. * 根据$queryCondition从多种数据源中查询数据
  144. * 并将结果插入中间表或者缓存
  145. * @param $queryCondition
  146. * @return Collection|mixed|\Tightenco\Collect\Support\Collection
  147. */
  148. public function getOrderCountingRecords($queryCondition)
  149. {
  150. list($orderCountingRecords_fromCache, $lackingCondition)
  151. = $this->getFromCache($queryCondition);
  152. if (empty($lackingCondition['data'])) {
  153. return $orderCountingRecords_fromCache;
  154. }
  155. list($orderCountingRecords_fromSelfTable, $lackingCondition)
  156. = $this->getFromMiddleTable($lackingCondition);
  157. if (empty($lackingCondition['data'])) {
  158. return $orderCountingRecords_fromCache->concat($orderCountingRecords_fromSelfTable);
  159. }
  160. /**
  161. * 1 如果查询粒度大于日 则进入getFromLowerUnit()
  162. * 2 如果查询粒度为日 则进入dataFromOrder()
  163. */
  164. if ($lackingCondition['unit'] != '日') {//日为最低粒度,不用进入此方法
  165. $orderCountingRecords_combinedByLower = $this->getFromLowerUnit($lackingCondition);
  166. } else {
  167. $orderCountingRecords_FromOrder = $this->dataFromOrder($lackingCondition);
  168. }
  169. $result = collect();
  170. if (isset($orderCountingRecords_FromOrder) && !$orderCountingRecords_FromOrder->isEmpty()) {
  171. $result = $result->concat($orderCountingRecords_FromOrder);
  172. }
  173. if (!$orderCountingRecords_fromCache->isEmpty()) {
  174. $result = $result->concat($orderCountingRecords_fromCache);
  175. }
  176. if (!$orderCountingRecords_fromSelfTable->isEmpty()) {
  177. $result = $result->concat($orderCountingRecords_fromSelfTable);
  178. }
  179. if (isset($orderCountingRecords_combinedByLower)) {
  180. $result = $result->concat($orderCountingRecords_combinedByLower);
  181. }
  182. return $result;
  183. }
  184. public function getFromLowerUnit($queryCondition)
  185. {
  186. switch ($queryCondition['unit']) {
  187. case '年':
  188. $lowUnit = '月';
  189. $conditionClone = ['unit' => $lowUnit, 'data' => []];
  190. foreach ($queryCondition['data'] as $date => $ownerIds) {
  191. $startAt = $date;
  192. $endAt = Carbon::parse($date)->endOfYear()->toDateString();
  193. $items = $this->transfersToCondition(
  194. $startAt, $endAt, $lowUnit, $ownerIds
  195. )['data'];
  196. foreach ($items as $dateStr => $item) {
  197. if (empty($conditionClone['data'][$dateStr])) $conditionClone['data'][$dateStr] = $dateStr;
  198. $conditionClone['data'][$dateStr] = ($item);
  199. }
  200. }
  201. $orderCountingRecords_days = $this->getOrderCountingRecords($conditionClone);
  202. $orderCountingRecords_combinedByLower = $this->turnGradingUpToLow($orderCountingRecords_days, $lowUnit, 'year');
  203. $this->insertIntoMiddleTable($orderCountingRecords_combinedByLower, '年');
  204. $this->insertIntoCache(collect($orderCountingRecords_combinedByLower), '年');
  205. break;
  206. case '月':
  207. $lowUnit = '日';
  208. $conditionClone = ['unit' => $lowUnit, 'data' => []];
  209. foreach ($queryCondition['data'] as $date => $ownerIds) {
  210. $startAt = $date;
  211. $endAt = Carbon::parse($date)->endOfMonth()->toDateString();
  212. $items = $this->transfersToCondition(
  213. $startAt, $endAt, $lowUnit, $ownerIds
  214. )['data'];
  215. foreach ($items as $dateStr => $item) {
  216. if (empty($conditionClone['data'][$dateStr])) $conditionClone['data'][$dateStr] = $dateStr;
  217. $conditionClone['data'][$dateStr] = ($item);
  218. }
  219. }
  220. $orderCountingRecords_days = $this->getOrderCountingRecords($conditionClone);
  221. $orderCountingRecords_combinedByLower = $this->turnGradingUpToLow($orderCountingRecords_days, $lowUnit, 'month');
  222. $this->insertIntoMiddleTable($orderCountingRecords_combinedByLower, '月');
  223. $this->insertIntoCache(collect($orderCountingRecords_combinedByLower), '月');
  224. break;
  225. case '日':
  226. return [[], $queryCondition];
  227. default:
  228. }
  229. return $orderCountingRecords_combinedByLower;
  230. }
  231. public function transfersToCondition($start, $end, $unit, $ownerIds): array
  232. {
  233. if (Carbon::parse($end)->gt(now())) $end = now()->toDateString();//如果$end超过当前时间,将end置为当前时间
  234. $condition = [
  235. 'data' => [],
  236. 'unit' => $unit,];
  237. $startAt = Carbon::parse($start);
  238. $dates = [];
  239. switch ($unit) {
  240. case '年':
  241. $dates = collect($startAt->yearsUntil($end, 1)->toArray())
  242. ->map(function (Carbon $date) {
  243. return $date->firstOfYear();
  244. });
  245. break;
  246. case '月':
  247. $dates = collect($startAt->monthsUntil($end, 1)->toArray())
  248. ->map(function (Carbon $date) {
  249. return $date->firstOfMonth();
  250. });
  251. break;
  252. case '日':
  253. $dates = collect($startAt->daysUntil($end, 1)->toArray())
  254. ->map(function (Carbon $date) {
  255. return $date->startOfDay();
  256. });
  257. break;
  258. default:
  259. }
  260. foreach ($dates as $day) {
  261. $condition['data'][$day->toDateString()] = $ownerIds;
  262. }
  263. return $condition;
  264. }
  265. public function dataFromOrder($queryCondition)
  266. {
  267. $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(updated_at,'%Y-%m-%d') as date_target");
  268. foreach ($queryCondition['data'] as $dateStr => $ownerIds) {
  269. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  270. $query->whereIn('owner_id', $ownerIds)->where('updated_at', '>=', $dateStr)->where('updated_at', '<', Carbon::parse($dateStr)->addDay()->toDateString())->where('wms_status', '订单完成');
  271. });
  272. }
  273. $dataFromOrder = $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  274. $dataFromMiddleTable = $this->ordersToOrderCountingRecords($dataFromOrder, $queryCondition['unit']);
  275. $this->setDefultData($dataFromMiddleTable, $queryCondition);
  276. $this->insertIntoMiddleTable($dataFromMiddleTable, $queryCondition['unit']);
  277. $this->insertIntoCache($dataFromMiddleTable, $queryCondition['unit']);
  278. return $dataFromMiddleTable;
  279. }
  280. public function insertIntoMiddleTable($data, $unit)
  281. {
  282. $filter = $data->filter(function ($item) use ($unit) {
  283. return $this->isNotCurrentDate($item->date_target, $unit);
  284. });
  285. $filter->chunk(1000)->each(function ($item) {
  286. OrderCountingRecord::query()->insert($item->toArray());
  287. });
  288. }
  289. public function insertIntoCache($collect, $unit)
  290. {
  291. $map = [];
  292. $collect->each(function ($order) use ($unit, &$map) {
  293. $key = "order_counting_records_{$order->date_target}_{$order->owner_id}_{$unit}";
  294. if (empty($map[$key])) $map[$key] = [];
  295. $map[$key][] = $order;
  296. });
  297. foreach ($map as $key => $orders) {
  298. Cache::put($key, collect($orders), $this->getTtl($orders[0]['date_target'], $unit));
  299. }
  300. }
  301. public function isNotCurrentDate($dateStr, $unit): bool
  302. {
  303. switch ($unit) {
  304. case '月':
  305. return !Carbon::parse($dateStr)->isCurrentMonth();
  306. case '年':
  307. return !Carbon::parse($dateStr)->isCurrentYear();
  308. default:
  309. return !Carbon::parse($dateStr)->isCurrentDay();
  310. }
  311. }
  312. public function unQueryCondition($dataFromMiddleTable, $unQueryCondition)
  313. {
  314. $map = [];
  315. $dataFromMiddleTable->each(function ($item) use (&$map) {
  316. $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target;
  317. $map[$key] = true;
  318. });
  319. foreach ($unQueryCondition['data'] as $dateStr => $ownerIds) {
  320. foreach ($ownerIds as $key => $ownerId) {
  321. $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr;
  322. if (isset($map[$key1])) {
  323. //中间表查找到数据
  324. unset($unQueryCondition['data'][$dateStr][$key]);
  325. }
  326. }
  327. if (empty($unQueryCondition['data'][$dateStr])) {
  328. unset($unQueryCondition['data'][$dateStr]);
  329. }
  330. }
  331. return $unQueryCondition;
  332. }
  333. public function ordersToOrderCountingRecords($dataFromOrder, $unit)
  334. {
  335. $dataFromMiddleTable = collect();
  336. //当日当周当月当年的数据不能插入到中间表
  337. $dateTime = Carbon::now()->toDateTimeString();
  338. foreach ($dataFromOrder as $order) {
  339. $carbon = Carbon::parse($order->date_target);
  340. $year = $carbon->year;
  341. $week = $carbon->week;
  342. $month = $carbon->month;
  343. $dataFromMiddleTable->push(new OrderCountingRecord([
  344. 'owner_id' => $order->owner_id,
  345. 'shop_id' => $order->shop_id,
  346. 'warehouse_id' => $order->warehouse_id,
  347. 'logistic_id' => $order->logistic_id,
  348. 'date_target' => $order->date_target,
  349. 'counting_unit' => $unit,
  350. 'amount' => $order->amounts ?? 0,
  351. 'week' => $year . '-' . $week,
  352. 'month' => $year . '-' . $month,
  353. 'year' => $year . '',
  354. 'created_at' => $dateTime,
  355. 'updated_at' => $dateTime,
  356. ]));
  357. }
  358. return $dataFromMiddleTable;
  359. }
  360. public function count($orderCountingRecords_days, $unit)
  361. {
  362. $isEnd = false;
  363. $result = collect();
  364. $item = null;
  365. $amount = 0;
  366. foreach ($orderCountingRecords_days as $itemToCount) {
  367. if ($itemToCount instanceof OrderCountingRecord) {
  368. if (!$isEnd) {
  369. $isEnd = true;
  370. $item = clone($itemToCount);
  371. }
  372. $amount += $itemToCount->amount;
  373. } else {
  374. $result = $result->concat($this->count($itemToCount, $unit));
  375. }
  376. }
  377. if ($isEnd) {
  378. switch ($unit) {
  379. case "日":
  380. $item['date_target'] = Carbon::parse($item['date_target'])->firstOfMonth()->toDateString();
  381. $item['counting_unit'] = '月';
  382. break;
  383. case "月":
  384. $item['date_target'] = Carbon::parse($item['date_target'])->firstOfYear()->toDateString();
  385. $item['counting_unit'] = '年';
  386. break;
  387. }
  388. $item['amount'] = $amount;
  389. return $result->push(new OrderCountingRecord([
  390. 'owner_id' => $item->owner_id,
  391. 'shop_id' => $item->shop_id,
  392. 'warehouse_id' => $item->warehouse_id,
  393. 'logistic_id' => $item->logistic_id,
  394. 'date_target' => $item->date_target,
  395. 'counting_unit' => $item->counting_unit,
  396. 'amount' => $item->amount,
  397. 'year' => $item->year,
  398. 'month' => $item->month,
  399. 'week' => $item->week
  400. ]));
  401. }
  402. return $result;
  403. }
  404. public function turnGradingUpToLow($orderCountingRecords_days, $unit, $grading)
  405. {
  406. $orderCountingRecords_days = $orderCountingRecords_days->groupBy(['owner_id', 'shop_id', 'warehouse_id', 'logistic_id', $grading]);
  407. return $this->count($orderCountingRecords_days, $unit);
  408. }
  409. public function setDefultData($dataFromMiddleTable, $queryCondition)
  410. {
  411. $map = [];
  412. foreach ($dataFromMiddleTable as $data) {
  413. if (empty($map[$data->date_target . '-' . $data->owner_id])) $map[$data->date_target . '-' . $data->owner_id] = true;
  414. }
  415. foreach ($queryCondition['data'] as $dateStr => $ownerIds) {
  416. foreach ($ownerIds as $ownerId) {
  417. if (empty($map[$dateStr . '-' . $ownerId]) && Carbon::parse($dateStr)->isBefore(Carbon::now())) {
  418. $carbon = Carbon::parse($dateStr);
  419. $year = $carbon->year;
  420. $week = $carbon->week;
  421. $month = $carbon->month;
  422. $dataFromMiddleTable->push(new OrderCountingRecord([
  423. 'owner_id' => $ownerId,
  424. 'shop_id' => null,
  425. 'warehouse_id' => null,
  426. 'logistic_id' => null,
  427. 'date_target' => $dateStr,
  428. 'counting_unit' => $queryCondition['unit'],
  429. 'amount' => 0,
  430. 'week' => $year . '-' . $week,
  431. 'month' => $year . '-' . $month,
  432. 'year' => $year . '',
  433. 'created_at' => $carbon->toDateString(),
  434. 'updated_at' => $carbon->toDateString(),
  435. ]));
  436. }
  437. }
  438. }
  439. }
  440. private function getTtl($dateStr, $unit)
  441. {
  442. if ($this->isNotCurrentDate($dateStr, $unit)) {
  443. LogService::log('NewOrderCountingRecordService', '缓存设置为永久', $dateStr);
  444. $ttl = config('cache.expirations.orderCountingRecord');//非当前日期的缓存为永久
  445. } else {
  446. LogService::log('NewOrderCountingRecordService', '缓存设置为临时', $dateStr);
  447. $ttl = config('cache.expirations.orderCountingRecord');//当前日期缓存为1800s
  448. }
  449. return $ttl;
  450. }
  451. public function getWareHouseRecordsApi($start, $end, $ownerIds): array
  452. {
  453. $orderCountingRecords = OrderCountingRecord::query()
  454. ->selectRaw("sum(amount) as value ,warehouse_id")
  455. ->with('warehouse:id,name,code')
  456. ->whereBetween('date_target', [$start, $end])
  457. ->whereIn('owner_id', $ownerIds)
  458. ->groupBy('warehouse_id')
  459. ->get();
  460. $result = [];
  461. foreach ($orderCountingRecords as $orderCountingRecord) {
  462. $result[] = [
  463. 'logistic_id' => $orderCountingRecord->warehouse_id,
  464. 'value' => $orderCountingRecord->value,
  465. 'name' => $orderCountingRecord->warehouse->name ?? '',
  466. 'code' => $orderCountingRecord->warehouse->code ?? '',
  467. ];
  468. }
  469. return $result;
  470. }
  471. public function getLogisticRecordsApi($start, $end, $ownerIds): array
  472. {
  473. $orderCountingRecords = OrderCountingRecord::query()
  474. ->selectRaw("sum(amount) as value ,logistic_id")
  475. ->with('logistic:id,name')
  476. ->whereBetween('date_target', [$start, $end])
  477. ->whereIn('owner_id', $ownerIds)
  478. ->groupBy('logistic_id')
  479. ->get();
  480. $result = [];
  481. foreach ($orderCountingRecords as $orderCountingRecord) {
  482. $result[] = [
  483. 'logistic_id' => $orderCountingRecord->logistic_id,
  484. 'value' => $orderCountingRecord->value,
  485. 'name' => $orderCountingRecord->logistic->name ?? '',
  486. ];
  487. }
  488. return $result;
  489. }
  490. /**
  491. * 查询订单量趋势
  492. * @param $start string
  493. * @param $end string
  494. * @param $unit string
  495. * @param $ownerIds array
  496. * @return Builder[]
  497. */
  498. public function getOrderCountingRecordsApi(string $start, string $end, string $unit, array $ownerIds): array
  499. {
  500. $orderCountingRecords = OrderCountingRecord::query()
  501. ->selectRaw("sum(amount) as counter ,date_target")
  502. ->whereBetween('date_target', [$start, $end])
  503. ->where('counting_unit', $unit)
  504. ->whereIn('owner_id', $ownerIds)
  505. ->groupBy('date_target')
  506. ->get()->toArray();
  507. if (now()->toDateString() == $end) {//查询时间包含当天
  508. switch ($unit) {
  509. case '日':
  510. //查询当天统计
  511. $startDateTime = Carbon::parse($end)->startOfDay()->toDateTimeString();
  512. $endDateTime = Carbon::parse($end)->endOfDay()->toDateTimeString();
  513. $date_format = "'%Y-%m-%d'";
  514. break;
  515. case '月':
  516. //查询当月统计
  517. $startDateTime = Carbon::parse($end)->startOfMonth()->startOfDay()->toDateTimeString();
  518. $endDateTime = Carbon::parse($end)->endOfMonth()->endOfDay()->toDateTimeString();
  519. $date_format = "'%Y-%m'";
  520. break;
  521. case '年':
  522. //查询当年统计
  523. $startDateTime = Carbon::parse($end)->startOfYear()->startOfDay()->toDateTimeString();
  524. $endDateTime = Carbon::parse($end)->endOfYear()->endOfDay()->toDateTimeString();
  525. $date_format = "'%Y'";
  526. break;
  527. }
  528. $order = Order::query()
  529. ->selectRaw("count(1) as amounts ,DATE_FORMAT(updated_at,{$date_format}) as date_target")
  530. ->whereBetween('updated_at', [$startDateTime, $endDateTime])
  531. ->where('wms_status', '订单完成')
  532. ->whereIn('owner_id', $ownerIds)
  533. ->groupBy('date_target')
  534. ->first();
  535. $orderCountingRecords[] = [
  536. "counter" => $order->amounts ?? 0,
  537. "date_target" => $order->date_target ?? (function () use ($unit) {
  538. switch ($unit) {
  539. case '日':
  540. return now()->toDateString();
  541. case '月':
  542. return now()->startOfMonth()->toDateString();
  543. case '年':
  544. return now()->startOfYear()->toDateString();
  545. }
  546. })(),
  547. ];
  548. }
  549. return $orderCountingRecords;
  550. }
  551. /**
  552. * 统计订单量 从$start 开始统计 默认截止到当前日期的前一天
  553. * @param $start string
  554. * @param null $end string
  555. * @param $unit string
  556. */
  557. public function recordOrder(string $start, $end = null, string $unit = '日')
  558. {
  559. ini_set('max_execution_time', 2 * 60 * 60);
  560. ini_set('memory_limit', '1024M');
  561. switch ($unit) {
  562. case '日':
  563. $this->recordByDay($start, $end, $unit);
  564. break;
  565. case'月':
  566. $this->recordByMonth($start, $end, $unit);
  567. break;
  568. case'年':
  569. $this->recordByYear($start, $end, $unit);
  570. break;
  571. default:
  572. }
  573. }
  574. /**
  575. * 清空统计缓存
  576. */
  577. public function clearCacheOrderRecord()
  578. {
  579. }
  580. /**
  581. * 日统计
  582. * @param string $start
  583. * @param $end
  584. * @param string $unit
  585. */
  586. public function recordByDay(string $start, $end = null, string $unit = '日'): void
  587. {
  588. $startDateTime = Carbon::parse($start)->startOfDay()->toDateTimeString();
  589. if (is_null($end)) {
  590. $end = now()->subDay()->endOfDay();
  591. }
  592. $endDateTime = Carbon::parse($end)->endOfDay()->toDateTimeString();
  593. Order::query()
  594. ->selectRaw("owner_id,warehouse_id,logistic_id,count(1) as amounts ,DATE_FORMAT(updated_at,'%Y-%m-%d') as date_target")
  595. ->whereBetween('updated_at', [$startDateTime, $endDateTime])
  596. ->where('wms_status', '订单完成')
  597. ->groupBy('owner_id', 'warehouse_id', 'logistic_id', 'date_target')
  598. ->chunk(1000, function ($orders) use ($unit) {
  599. $insertData = [];
  600. foreach ($orders as $order) {
  601. $insertData[] = [
  602. 'owner_id' => $order->owner_id,
  603. 'warehouse_id' => $order->warehouse_id,
  604. 'logistic_id' => $order->logistic_id,
  605. 'date_target' => $order->date_target,
  606. 'counting_unit' => $unit,
  607. 'amount' => $order->amounts ?? 0,
  608. 'year' => Carbon::parse($order->date_target)->year,
  609. 'month' => Carbon::parse($order->date_target)->year . '-' . Carbon::parse($order->date_target)->month,
  610. ];
  611. }
  612. OrderCountingRecord::query()->insert($insertData);
  613. });
  614. }
  615. public function recordByMonth(string $start, $end = null, $unit = '月')
  616. {
  617. $startDate = Carbon::parse($start)->startOfMonth()->toDateString();
  618. if (is_null($end)) {
  619. $end = now()->subMonth()->endOfDay();
  620. }
  621. $endDate = Carbon::parse($end)->endOfDay()->toDateString();
  622. OrderCountingRecord::query()
  623. ->selectRaw("owner_id,warehouse_id,logistic_id,sum(amount) as amount_sum,month,year,date_target")
  624. ->whereBetween('date_target', [$startDate, $endDate])
  625. ->where('counting_unit', '日')
  626. ->groupBy('owner_id', 'warehouse_id', 'logistic_id', 'month')
  627. ->chunk(1000, function ($records) use ($unit) {
  628. $insertData = [];
  629. foreach ($records as $record) {
  630. $insertData[] = [
  631. 'owner_id' => $record->owner_id,
  632. 'warehouse_id' => $record->warehouse_id,
  633. 'logistic_id' => $record->logistic_id,
  634. 'counting_unit' => $unit,
  635. 'date_target' => Carbon::parse($record->date_target)->startOfMonth()->toDateString(),
  636. 'amount' => $record->amount_sum,
  637. 'year' => $record->year,
  638. 'month' => $record->month,
  639. ];
  640. }
  641. OrderCountingRecord::query()->insertOrIgnore($insertData);
  642. });
  643. }
  644. public function recordByYear(string $start, $end = null, $unit = '年')
  645. {
  646. $startYear = Carbon::parse($start)->year;
  647. if (is_null($end)) {
  648. $end = now()->subYear()->toDateString();
  649. }
  650. $endYear = Carbon::parse($end)->year;
  651. $orderCountingRecords = OrderCountingRecord::query()
  652. ->selectRaw("owner_id,warehouse_id,logistic_id,sum(amount) as amount_sum,year,date_target")
  653. ->whereBetween('year', [$startYear, $endYear])
  654. ->groupBy('owner_id', 'warehouse_id', 'logistic_id', 'year')
  655. ->get();
  656. $insertData = [];
  657. foreach ($orderCountingRecords as $orderCountingRecord) {
  658. $insertData[] = [
  659. 'owner_id' => $orderCountingRecord->owner_id,
  660. 'warehouse_id' => $orderCountingRecord->warehouse_id,
  661. 'logistic_id' => $orderCountingRecord->logistic_id,
  662. 'counting_unit' => $unit,
  663. 'date_target' => Carbon::parse($orderCountingRecord->date_target)->startOfYear()->toDateString(),
  664. 'amount' => $orderCountingRecord->amount_sum,
  665. 'year' => $orderCountingRecord->year,
  666. ];
  667. }
  668. OrderCountingRecord::query()->insertOrIgnore($insertData);
  669. }
  670. }