NewOrderCountingRecordService.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. namespace App\Services;
  3. use App\Order;
  4. use App\OrderCountingRecord;
  5. use Carbon\Carbon;
  6. use Illuminate\Support\Arr;
  7. use Illuminate\Support\Facades\Cache;
  8. class NewOrderCountingRecordService
  9. {
  10. public function orderCountingRecords($start, $end, $unit)
  11. {
  12. $key = 'orderCountingRecords_' . $start . '_' . $end . '_' . $unit . '_' . auth()->id();
  13. return \cache()->remember($key, 600, function () use ($start, $end, $unit) {
  14. $result = collect();
  15. switch ($unit) {
  16. case '日':
  17. $result = $this->orderCountingRecordsDay($start, $end, $unit);
  18. break;
  19. case '周':
  20. $result = $this->orderCountingRecordsWeek($start, $end, $unit);
  21. break;
  22. case '月':
  23. $result = $this->orderCountingRecordsMonth($start, $end, $unit);
  24. break;
  25. case '年':
  26. $result = $this->orderCountingRecordsYear($start, $end, $unit);
  27. break;
  28. default:
  29. break;
  30. }
  31. return $result;
  32. });
  33. }
  34. public function getCountingOwnerIds($ownerIds = null): array
  35. {
  36. $user = auth()->user();
  37. /** @var UserService $userService */
  38. $userService = app('UserService');
  39. $permittingOwnerIds = $userService->getPermittingOwnerIds($user);
  40. if (!$ownerIds) {
  41. return $permittingOwnerIds;
  42. }
  43. return Cache::remember(
  44. 'PermittingOwnerIds' . '_' . auth()->user()->id . '_' . implode('_', $ownerIds),
  45. 600, function () use ($ownerIds, $permittingOwnerIds) {
  46. /** @var User $user */
  47. return array_intersect($ownerIds, $permittingOwnerIds);
  48. });
  49. }
  50. public function dataFromCache($start, $end, $unit)
  51. {
  52. $result = [];
  53. $unQueryCondition = [];
  54. $dataFromCache = collect();
  55. $queryCondition = $this->dateUtils($start, $end, $unit);
  56. foreach ($queryCondition as $dateStr => $ownerIds) {
  57. foreach ($ownerIds as $ownerId) {
  58. $key = 'order_counting_records_' . $dateStr . '_' . $ownerId . '_' . $unit . '_' . auth()->id();
  59. $items = cache()->get($key);
  60. if (empty($items)) {
  61. if (empty($unQueryCondition[$dateStr])) $unQueryCondition[$dateStr] = [];
  62. $unQueryCondition[$dateStr][] = $ownerId;
  63. } else {
  64. $dataFromCache = $dataFromCache->concat($items);
  65. }
  66. }
  67. }
  68. $result['dataFromCache'] = $dataFromCache;
  69. $result['unQueryCondition'] = $unQueryCondition;
  70. return $result;
  71. }
  72. public function dataFromMiddleTable($unQueryCondition, $unit)
  73. {
  74. $result = [];
  75. $orderSqlBuilder = OrderCountingRecord::query();
  76. foreach ($unQueryCondition as $date => $owners) {
  77. $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) {
  78. $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit);
  79. });
  80. }
  81. $dataFromMiddleTable = $orderSqlBuilder->get();
  82. $this->insertIntoCache($dataFromMiddleTable, $unit);
  83. $unQueryCondition = $this->unQueryCondition($dataFromMiddleTable, $unQueryCondition);
  84. $result['unQueryCondition'] = $unQueryCondition;
  85. $result['dataFromMiddleTable'] = $dataFromMiddleTable;
  86. return $result;
  87. }
  88. public function orderCountingRecordsDay($start, $end, $unit)
  89. {
  90. $dataFromCacheResult = $this->dataFromCache($start, $end, $unit);
  91. $dataFromCache = $dataFromCacheResult['dataFromCache'];
  92. $unQueryCondition = $dataFromCacheResult['unQueryCondition'];
  93. if (!empty($unQueryCondition)) {
  94. $dataFromMiddleTableResult = $this->dataFromMiddleTable($unQueryCondition, $unit);
  95. $dataFromMiddleTable = $dataFromMiddleTableResult['dataFromMiddleTable'];
  96. $unQueryCondition = $dataFromMiddleTableResult['unQueryCondition'];
  97. if (!empty($unQueryCondition)) {
  98. $dataFromOrder = $this->dataFromOrder($unQueryCondition, $unit);
  99. }
  100. }
  101. $dataFromCache = $dataFromCache ?? collect();
  102. $dataFromMiddleTable = $dataFromMiddleTable ?? collect();
  103. $dataFromOrder = $dataFromOrder ?? collect();
  104. return $dataFromCache->concat($dataFromMiddleTable)->concat($dataFromOrder);
  105. }
  106. public function dateUtils($start, $end, $unit)
  107. {
  108. $ownerIds = $this->getCountingOwnerIds();
  109. $dataArray = [];
  110. switch ($unit) {
  111. case '日';
  112. foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
  113. $dataArray[$item->toDateString()] = $ownerIds;
  114. }
  115. break;
  116. case '周';
  117. foreach (Carbon::parse($start)->weeksUntil($end, 1)->toArray() as $item) {
  118. $dataArray[$item->year . '-' . $item->week . ''] = $ownerIds;
  119. }
  120. break;
  121. case '月';
  122. foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) {
  123. $dataArray[$item->year . '-' . $item->format('m') . ''] = $ownerIds;
  124. }
  125. break;
  126. case '年';
  127. foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) {
  128. $dataArray[$item->year] = $ownerIds;
  129. }
  130. break;
  131. default:
  132. break;
  133. }
  134. return $dataArray;
  135. }
  136. public function dataFromOrder($unQueryCondition, $unit)
  137. {
  138. $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%Y-%m-%d') as date_target");
  139. foreach ($unQueryCondition as $dateStr => $ownerIds) {
  140. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  141. $query->whereIn('owner_id', $ownerIds)->where('created_at', '>', $dateStr)->where('created_at', '<', Carbon::parse($dateStr)->addDay()->toDateString())->where('wms_status', '订单完成');
  142. });
  143. }
  144. $dataFromOrder = $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  145. $dataFromMiddleTable = $this->ordersToOrderCountingRecords($dataFromOrder);
  146. $this->insertIntoMiddleTable($dataFromMiddleTable, $unit);
  147. $this->insertIntoCache($dataFromMiddleTable, $unit);
  148. return $dataFromMiddleTable;
  149. }
  150. public function orderCountingRecordsWeek($start, $end, $unit)
  151. {
  152. //TODO
  153. return collect();
  154. }
  155. public function orderCountingRecordsMonth($start, $end, $unit)
  156. {
  157. //TODO
  158. return collect();
  159. }
  160. public function orderCountingRecordsYear($start, $end, $unit)
  161. {
  162. //TODO
  163. return collect();
  164. }
  165. public function insertIntoMiddleTable($data, $unit)
  166. {
  167. $data->filter(function ($item) {
  168. return $this->isNotCurrentDate($item->date_target);
  169. })->chunk(1000)->each(function ($item) {
  170. OrderCountingRecord::query()->insert($item->toArray());
  171. });
  172. }
  173. public function insertIntoCache($collect, $unit)
  174. {
  175. $map = [];
  176. $collect->each(function ($order) use ($unit, &$map) {
  177. $key = "order_counting_records_{$order->date_target}_{$order->owner_id}_{$unit}";
  178. if (empty($map[$key])) $map[$key] = [];
  179. $map[$key][] = $order;
  180. });
  181. foreach ($map as $key => $orders) {
  182. $ttl = 3600 * 24;
  183. if (!$this->isNotCurrentDate($orders[0]['date_target'])) {
  184. $ttl = 70;
  185. }
  186. Cache::put($key, collect($orders), $ttl);
  187. }
  188. }
  189. public function isNotCurrentDate($dateStr): bool
  190. {
  191. return $dateStr != Carbon::now()->format('Y-m-d')
  192. && $dateStr != Carbon::now()->year . '-' . Carbon::now()->week
  193. && $dateStr != Carbon::now()->year . '-' . Carbon::now()->month;
  194. }
  195. public function unQueryCondition($dataFromMiddleTable, $unQueryCondition)
  196. {
  197. $map = [];
  198. $dataFromMiddleTable->each(function ($item) use (&$map) {
  199. $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target;
  200. $map[$key] = true;
  201. });
  202. foreach ($unQueryCondition as $dateStr => $ownerIds) {
  203. foreach ($ownerIds as $key => $ownerId) {
  204. $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr;
  205. if (isset($map[$key1])) {
  206. //中间表查找到数据
  207. unset($unQueryCondition[$dateStr][$key]);
  208. }
  209. }
  210. }
  211. return $unQueryCondition;
  212. }
  213. public function ordersToOrderCountingRecords($dataFromOrder)
  214. {
  215. $dataFromMiddleTable = collect();
  216. //当日当周当月当年的数据不能插入到中间表
  217. $dateTime = Carbon::now()->toDateTimeString();
  218. foreach ($dataFromOrder as $order) {
  219. $dataFromMiddleTable->push(new OrderCountingRecord([
  220. 'owner_id' => $order->owner_id,
  221. 'shop_id' => $order->shop_id,
  222. 'warehouse_id' => $order->warehouse_id,
  223. 'logistic_id' => $order->logistic_id,
  224. 'date_target' => $order->date_target,
  225. 'counting_unit' => $order->counting_unit,
  226. 'amount' => $order->amounts,
  227. 'created_at' => $dateTime,
  228. 'updated_at' => $dateTime,
  229. ]));
  230. }
  231. return $dataFromMiddleTable;
  232. }
  233. }