NewOrderCountingRecordService.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <?php
  2. namespace App\Services;
  3. use App\Order;
  4. use App\OrderCountingRecord;
  5. use Carbon\Carbon;
  6. use Illuminate\Support\Facades\Cache;
  7. use Illuminate\Support\Str;
  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($unQueryCondition, $unit)
  57. {
  58. $result = [];
  59. $orderSqlBuilder = OrderCountingRecord::query();
  60. foreach ($unQueryCondition as $date => $owners) {
  61. $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) {
  62. $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit);
  63. });
  64. }
  65. $dataFromMiddleTable = $orderSqlBuilder->get();
  66. $this->insertIntoCache($dataFromMiddleTable, $unit);
  67. $unQueryCondition = $this->unQueryCondition($dataFromMiddleTable, $unQueryCondition);
  68. $result['unQueryCondition'] = $unQueryCondition;
  69. $result['dataFromMiddleTable'] = $dataFromMiddleTable;
  70. return $result;
  71. }
  72. public function getOrderCountingRecords($queryCondition)
  73. {
  74. list($orderCountingRecords_fromCache, $lackingCondition)
  75. = $this->getFromCache($queryCondition);
  76. if (empty($lackingCondition['data'])) {
  77. return $orderCountingRecords_fromCache;
  78. }
  79. list($orderCountingRecords_fromSelfTable, $lackingCondition)
  80. = $this->dataFromMiddleTable($lackingCondition);
  81. if (empty($lackingCondition['data'])) {
  82. return $orderCountingRecords_fromCache->concat($orderCountingRecords_fromSelfTable);
  83. }
  84. list($orderCountingRecords_combinedByLower, $lackingCondition)
  85. = $this->getByLowerUnit($lackingCondition);
  86. $orderCountingRecords_FromOrder = $this->dataFromOrder($lackingCondition);
  87. return $orderCountingRecords_FromOrder
  88. ->concat($orderCountingRecords_fromCache)
  89. ->concat($orderCountingRecords_fromSelfTable)
  90. ->concat($orderCountingRecords_combinedByLower);
  91. }
  92. public function getByLowerUnit($queryCondition)
  93. {
  94. switch ($queryCondition['unit']) {
  95. case '年':
  96. break;
  97. case '月':
  98. break;
  99. case '周':
  100. $conditionClone = ['unit' => '日', 'data' => collect([])];
  101. foreach ($queryCondition['data'] as $date => $ownerIds) {
  102. $startAt = $date;
  103. $endAt = Carbon::parse($date)->endOfWeek()->toDateString();
  104. $conditionClone['data']->concat(
  105. $this->transfersToCondition(
  106. $startAt, $endAt, $queryCondition['unit'], $ownerIds
  107. )['data']
  108. );
  109. }
  110. $conditionClone['data'] = $conditionClone['data']->toArray();
  111. $orderCountingRecords_days = $this->getOrderCountingRecords($conditionClone);
  112. //TODO: func turnDaysToWeeks($orderCountingRecords_days): 变成 ..._weeks
  113. $orderCountingRecords_combinedByLower = $this->turnDaysToWeeks($orderCountingRecords_days);
  114. break;
  115. case '日':
  116. return [[], $queryCondition];
  117. break;
  118. default:
  119. }
  120. return [[], $orderCountingRecords_combinedByLower];
  121. }
  122. public function transfersToCondition($start, $end, $unit, $ownerIds)
  123. {
  124. $condition = [
  125. 'data' => [],
  126. 'unit' => $unit,];
  127. $startAt = Carbon::parse($start);
  128. $dates = [];
  129. switch ($unit) {
  130. case '年':
  131. $dates = collect($startAt->yearsUntil($end, 1)->toArray())
  132. ->map(function (Carbon $date) {
  133. return $date->firstOfYear();
  134. });
  135. break;
  136. case '月':
  137. $dates = collect($startAt->monthsUntil($end, 1)->toArray())
  138. ->map(function (Carbon $date) {
  139. return $date->firstOfMonth();
  140. });
  141. break;
  142. case '周':
  143. $dates = collect($startAt->weeksUntil($end, 1)->toArray())
  144. ->map(function (Carbon $date) {
  145. return $date->startOfWeek();
  146. });
  147. break;
  148. case '日':
  149. $dates = collect($startAt->daysUntil($end, 1)->toArray())
  150. ->map(function (Carbon $date) {
  151. return $date->startOfDay();
  152. });
  153. break;
  154. default:
  155. }
  156. foreach ($dates as $day) {
  157. $condition['data'][$day->toDateString()] = $ownerIds;
  158. }
  159. return $condition;
  160. }
  161. public function dataFromOrder($unQueryCondition, $unit)
  162. {
  163. $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");
  164. foreach ($unQueryCondition as $dateStr => $ownerIds) {
  165. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  166. $query->whereIn('owner_id', $ownerIds)->where('created_at', '>', $dateStr)->where('created_at', '<', Carbon::parse($dateStr)->addDay()->toDateString())->where('wms_status', '订单完成');
  167. });
  168. }
  169. $dataFromOrder = $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  170. $dataFromMiddleTable = $this->ordersToOrderCountingRecords($dataFromOrder);
  171. $this->insertIntoMiddleTable($dataFromMiddleTable, $unit);
  172. $this->insertIntoCache($dataFromMiddleTable, $unit);
  173. return $dataFromMiddleTable;
  174. }
  175. public function insertIntoMiddleTable($data, $unit)
  176. {
  177. $data->filter(function ($item) {
  178. return $this->isNotCurrentDate($item->date_target);
  179. })->chunk(1000)->each(function ($item) {
  180. OrderCountingRecord::query()->insert($item->toArray());
  181. });
  182. }
  183. public function insertIntoCache($collect, $unit)
  184. {
  185. $map = [];
  186. $collect->each(function ($order) use ($unit, &$map) {
  187. $key = "order_counting_records_{$order->date_target}_{$order->owner_id}_{$unit}";
  188. if (empty($map[$key])) $map[$key] = [];
  189. $map[$key][] = $order;
  190. });
  191. foreach ($map as $key => $orders) {
  192. $ttl = 3600 * 24;
  193. if (!$this->isNotCurrentDate($orders[0]['date_target'])) {
  194. $ttl = 70;
  195. }
  196. Cache::put($key, collect($orders), $ttl);
  197. }
  198. }
  199. public function isNotCurrentDate($dateStr): bool
  200. {
  201. return $dateStr != Carbon::now()->format('Y-m-d')
  202. && $dateStr != Carbon::now()->year . '-' . Carbon::now()->week
  203. && $dateStr != Carbon::now()->year . '-' . Carbon::now()->month;
  204. }
  205. public function unQueryCondition($dataFromMiddleTable, $unQueryCondition)
  206. {
  207. $map = [];
  208. $dataFromMiddleTable->each(function ($item) use (&$map) {
  209. $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target;
  210. $map[$key] = true;
  211. });
  212. foreach ($unQueryCondition as $dateStr => $ownerIds) {
  213. foreach ($ownerIds as $key => $ownerId) {
  214. $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr;
  215. if (isset($map[$key1])) {
  216. //中间表查找到数据
  217. unset($unQueryCondition[$dateStr][$key]);
  218. }
  219. }
  220. }
  221. return $unQueryCondition;
  222. }
  223. public function ordersToOrderCountingRecords($dataFromOrder)
  224. {
  225. $dataFromMiddleTable = collect();
  226. //当日当周当月当年的数据不能插入到中间表
  227. $dateTime = Carbon::now()->toDateTimeString();
  228. foreach ($dataFromOrder as $order) {
  229. $carbon = Carbon::parse($order->date_target);
  230. $year = $carbon->year;
  231. $week = $carbon->week;
  232. $month = $carbon->month;
  233. $dataFromMiddleTable->push(new OrderCountingRecord([
  234. 'owner_id' => $order->owner_id,
  235. 'shop_id' => $order->shop_id,
  236. 'warehouse_id' => $order->warehouse_id,
  237. 'logistic_id' => $order->logistic_id,
  238. 'date_target' => $order->date_target,
  239. 'counting_unit' => $order->counting_unit,
  240. 'amount' => $order->amounts,
  241. 'week' => $year . '-' . $week,
  242. 'month' => $year . '-' . $month,
  243. 'year' => $year,
  244. 'created_at' => $dateTime,
  245. 'updated_at' => $dateTime,
  246. ]));
  247. }
  248. return $dataFromMiddleTable;
  249. }
  250. public function dateSwitch($unQueryCondition, $currentUnit, $targetUnit)
  251. {
  252. foreach ($unQueryCondition as $date => $ownerIds) {
  253. switch ($currentUnit . '-' . $targetUnit) {
  254. case '周-日':
  255. $week = Str::of($date)->after('-');
  256. $year = Str::of($date)->before('-');
  257. break;
  258. case '月-周':
  259. break;
  260. case '年-月':
  261. break;
  262. default:
  263. break;
  264. }
  265. }
  266. return [];
  267. }
  268. public function turnDaysToWeeks($orderCountingRecords_days)
  269. {
  270. $orderCountingRecords_combinedByLower = collect();
  271. foreach ($orderCountingRecords_days as $orderCountingRecord) {
  272. $date_target = $orderCountingRecord->date_target;
  273. }
  274. }
  275. }