OrderCountingRecordService.php 13 KB

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