OrderCountingRecordService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. namespace App\Services;
  3. use App\Order;
  4. use App\OrderCountingRecord;
  5. use Carbon\Carbon;
  6. use DateTime;
  7. use Illuminate\Database\Eloquent\Collection;
  8. use Illuminate\Support\Facades\Cache;
  9. use App\User;
  10. use Illuminate\Support\Str;
  11. class OrderCountingRecordService
  12. {
  13. /** @var $ownerService OwnerService */
  14. private $ownerService = null;
  15. function __construct()
  16. {
  17. $this->ownerService = app(OwnerService::class);
  18. }
  19. public function get($start, $end, $ownerIds = null, $unit = '日')
  20. {
  21. $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit);
  22. if (!($resultByCache['unExistingOrders'])) return $resultByCache['resultOrders'];
  23. $resultByOrderCountingRecords = $this->getByDatabase($resultByCache['unExistingOrders'], $unit);
  24. $this->createByDatabase($resultByOrderCountingRecords['unExistingOrders'], $unit);
  25. $this->getByDatabase($resultByCache['unExistingOrders'], $unit);
  26. $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit);
  27. return $resultByCache['resultOrders'];
  28. }
  29. public function orderCountingRecords($start, $end, $unit = '日')
  30. {
  31. $orders = $this->get($start, $end, null, $unit);
  32. $dataList = collect();
  33. $orders->groupBy('date_target')->each(function ($items) use (&$dataList, $unit) {
  34. $counter = $items->reduce(function ($sum, $item) {
  35. return $sum + $item->amount;
  36. }, 0);
  37. $date_target = $items[0]->date_target;
  38. if ($unit == '周') {
  39. $date_target = (new DateTime())->setISODate(Str::of($date_target)->explode('-')[0], Str::of($date_target)->explode('-')[1])->format('yy-m-d');
  40. }
  41. $dataList->push([
  42. 'counter' => $counter,
  43. 'date_target' => $date_target,
  44. ]);
  45. });
  46. return $dataList->sortBy("date_target");
  47. }
  48. public function logisticsCountingRecords($start, $end, $ownerIds = null)
  49. {
  50. $dataList = collect();
  51. $resultOrders = $this->get($start, $end, $ownerIds);
  52. $resultOrders->groupBy('logistic_id')->each(function ($item)use(&$dataList) {
  53. $counter = $item->reduce(function ($sum, $item) {
  54. return $sum + $item->amount;
  55. }, 0);
  56. $dataList->push([
  57. 'counter' => $counter,
  58. 'logistic_id' => $date_target,
  59. ]);
  60. });
  61. }
  62. public function getByCache($start, $end, $ownerIds = null, $unit = '日')
  63. {// Order[] results, Array [$date=>[$ownerIds]]
  64. $countingOwnerIds = $this->getCountingOwnerIds($ownerIds);
  65. $resultOrders = collect();
  66. $unExistingOrders = [];
  67. $carbonInterfaces = $this->periodDateToArray($start, $end, $unit);
  68. foreach ($carbonInterfaces as $dateStr) {
  69. foreach ($countingOwnerIds as $ownerId) {
  70. $key = "order_counting_records_{$dateStr}_{$ownerId}_{$unit}";
  71. $orders = Cache::get($key);
  72. if ($orders) {
  73. $orders->each(function ($item) use (&$resultOrders) {
  74. $resultOrders->push($item);
  75. });
  76. continue;
  77. }
  78. $unExistingOrders[$dateStr][] = $ownerId;
  79. }
  80. }
  81. return ['resultOrders' => $resultOrders, 'unExistingOrders' => $unExistingOrders];
  82. }
  83. public function getByDatabase($targetOwnerIdsUnderDates, $unit = '日')
  84. {// Order[] results, Array [$date=>[$ownerIds]]
  85. $orderSqlBuilder = OrderCountingRecord::query();
  86. foreach ($targetOwnerIdsUnderDates as $date => $owners) {
  87. $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) {
  88. $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit);
  89. });
  90. }
  91. $resultOrders = $orderSqlBuilder->get();
  92. $resultOrders->groupBy(['date_target', 'owner_id'])->each(function ($item, $dateStr) use ($unit) {
  93. $item->each(function ($item, $owner_id) use ($dateStr, $unit) {
  94. $key = "order_counting_records_{$dateStr}_{$owner_id}_{$unit}";
  95. Cache::put($key, $item, 600);
  96. });
  97. });
  98. $map = [];
  99. $resultOrders->each(function ($item) use (&$map) {
  100. $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target;
  101. $map[$key] = true;
  102. });
  103. foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
  104. foreach ($ownerIds as $key => $ownerId) {
  105. $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr;
  106. if (isset($map[$key1])) {
  107. unset($targetOwnerIdsUnderDates[$dateStr][$key]);
  108. }
  109. }
  110. }
  111. return ['resultOrders' => $resultOrders, 'unExistingOrders' => $targetOwnerIdsUnderDates];
  112. }
  113. public function createByDatabase($targetOwnerIdsUnderDates, $unit = '日')
  114. {// Order[] results]
  115. switch ($unit) {
  116. case '日':
  117. $resultOrders = $this->getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates);
  118. break;
  119. case'周':
  120. $resultOrders = $this->getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates);
  121. break;
  122. case'月':
  123. $resultOrders = $this->getCreateByDatabaseUnitMounth($targetOwnerIdsUnderDates);
  124. break;
  125. default:
  126. $resultOrders = collect();
  127. break;
  128. }
  129. $result = collect();
  130. $resultOrders->each(function ($order) use (&$result, $unit) {
  131. $orderCountingRecord = new OrderCountingRecord([
  132. 'owner_id' => $order->owner_id,
  133. 'shop_id' => $order->shop_id,
  134. 'warehouse_id' => $order->warehouse_id,
  135. 'logistic_id' => $order->logistic_id,
  136. 'date_target' => $order->date_target,
  137. 'counting_unit' => $unit,
  138. 'amount' => $order->amounts,
  139. ]);
  140. $result->push($orderCountingRecord);
  141. });
  142. OrderCountingRecord::query()->insert($result->toArray());
  143. return ['resultOrders' => $result];
  144. }
  145. public function periodDateToArray($start, $end, $unit = '日')
  146. {
  147. $dataArray = [];
  148. switch ($unit) {
  149. case '日';
  150. foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
  151. $dataArray[] = $item->toDateString();
  152. }
  153. break;
  154. case '周';
  155. foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) {
  156. $dataArray[] = $item->year . '-' . $item->week . '';
  157. }
  158. break;
  159. case '月';
  160. foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) {
  161. $dataArray[] = $item->year . '-' . $item->month . '';
  162. }
  163. break;
  164. case '年';
  165. foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) {
  166. $dataArray[] = $item->year . '-' . $item->month . '';
  167. }
  168. break;
  169. default:
  170. break;
  171. }
  172. return $dataArray;
  173. }
  174. /**
  175. * @param $ownerIds
  176. * @return array
  177. */
  178. public function getCountingOwnerIds($ownerIds = null): array
  179. {
  180. $user = auth()->user();
  181. /** @var UserService $userService */
  182. $userService = app('UserService');
  183. $permittingOwnerIds = $userService->getPermittingOwnerIds($user);
  184. if (!$ownerIds) {
  185. return $permittingOwnerIds;
  186. }
  187. return Cache::remember(
  188. 'PermittingOwnerIds' . '_' . auth()->user()->id . '_' . implode('_', $ownerIds),
  189. config('cache.rarelyChange'), function () use ($ownerIds, $permittingOwnerIds) {
  190. /** @var User $user */
  191. return array_intersect($ownerIds, $permittingOwnerIds);
  192. });
  193. }
  194. /**
  195. * @param $targetOwnerIdsUnderDates
  196. * @return \Illuminate\Database\Eloquent\Builder[]|Collection
  197. */
  198. private function getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates)
  199. {
  200. $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");
  201. foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
  202. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  203. $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', $dateStr)->where('wms_status', '订单完成');
  204. });
  205. }
  206. return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  207. }
  208. private function getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates)
  209. {
  210. $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%x-%v') as date_target");
  211. foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
  212. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  213. $dateStr = (new DateTime())->setISODate(Str::of($dateStr)->explode('-')[0], Str::of($dateStr)->explode('-')[1])->format('yy-m-d');
  214. $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', '>=', $dateStr)->whereDate('created_at', '<', Carbon::parse($dateStr)->addWeek()->toDateString())->where('wms_status', '订单完成');;
  215. });
  216. }
  217. return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  218. }
  219. private function getCreateByDatabaseUnitMounth($targetOwnerIdsUnderDates)
  220. {
  221. $orderSqlBuilder = Order::query()->selectRaw("owner_id,warehouse_id,shop_id,logistic_id,count(1) as amounts ,DATE_FORMAT(created_at,'%Y-%m') as date_target");
  222. foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) {
  223. $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) {
  224. $year = Str::of($dateStr)->explode('-')[0];
  225. $month = Str::of($dateStr)->explode('-')[1];
  226. $query->whereIn('owner_id', $ownerIds)->whereMonth('created_at', $month)->whereYear('created_at', $year)->where('wms_status', '订单完成');;
  227. });
  228. }
  229. return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get();
  230. }
  231. }