OrderCountingRecordService.php 14 KB

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