NewOrderCountingRecordService.php 12 KB

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