ownerService = app(OwnerService::class); } public function get($start, $end, $ownerIds = null, $unit = '日') { $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit); if (!($resultByCache['unExistingOrders'])) return $resultByCache['resultOrders']; $resultByOrderCountingRecords = $this->getByDatabase($resultByCache['unExistingOrders'], $unit); $this->createByDatabase($resultByOrderCountingRecords['unExistingOrders'], $unit); $this->getByDatabase($resultByCache['unExistingOrders'], $unit); $resultByCache = $this->getByCache($start, $end, $ownerIds, $unit); return $resultByCache['resultOrders']; } public function getByCache($start, $end, $ownerIds = null, $unit = '日') {// Order[] results, Array [$date=>[$ownerIds]] $countingOwnerIds = $this->getCountingOwnerIds($ownerIds); $resultOrders = collect(); $unExistingOrders = []; $carbonInterfaces = $this->periodDateToArray($start, $end, $unit); foreach ($carbonInterfaces as $dateStr) { foreach ($countingOwnerIds as $ownerId) { $key = "order_counting_records_{$dateStr}_{$ownerId}_{$unit}"; $orders = Cache::get($key); if ($orders) { $orders->each(function ($item) use (&$resultOrders) { $resultOrders->push($item); }); continue; } $unExistingOrders[$dateStr][] = $ownerId; } } return ['resultOrders' => $resultOrders, 'unExistingOrders' => $unExistingOrders]; } public function getByDatabase($targetOwnerIdsUnderDates, $unit = '日') {// Order[] results, Array [$date=>[$ownerIds]] $orderSqlBuilder = OrderCountingRecord::query(); foreach ($targetOwnerIdsUnderDates as $date => $owners) { $orderSqlBuilder->orWhere(function ($query) use ($owners, $date, $unit) { $query->whereIn('owner_id', $owners)->where('date_target', $date)->where('counting_unit', $unit); }); } $resultOrders = $orderSqlBuilder->get(); $resultOrders->groupBy(['date_target', 'owner_id'])->each(function ($item, $dateStr) use ($unit) { $item->each(function ($item, $owner_id) use ($dateStr, $unit) { $key = "order_counting_records_{$dateStr}_{$owner_id}_{$unit}"; Cache::put($key, $item, 600); }); }); $map = []; $resultOrders->each(function ($item) use (&$map) { $key = 'owner_id=' . $item->owner_id . ' date_target' . $item->date_target; $map[$key] = true; }); foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) { foreach ($ownerIds as $key => $ownerId) { $key1 = 'owner_id=' . $ownerId . ' date_target' . $dateStr; if (isset($map[$key1])) { unset($targetOwnerIdsUnderDates[$dateStr][$key]); } } } return ['resultOrders' => $resultOrders, 'unExistingOrders' => $targetOwnerIdsUnderDates]; } public function createByDatabase($targetOwnerIdsUnderDates, $unit = '日') {// Order[] results] switch ($unit) { case '日': $resultOrders = $this->getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates); break; case'周': $resultOrders = $this->getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates); break; case'月': $resultOrders = $this->getCreateByDatabaseUnitMounth($targetOwnerIdsUnderDates); break; default: $resultOrders = collect(); break; } $result = collect(); $resultOrders->each(function ($order) use (&$result, $unit) { $orderCountingRecord = new OrderCountingRecord([ 'owner_id' => $order->owner_id, 'shop_id' => $order->shop_id, 'warehouse_id' => $order->warehouse_id, 'logistic_id' => $order->logistics_id, 'date_target' => $order->date_target, 'counting_unit' => $unit, 'amount' => $order->amounts, ]); $result->push($orderCountingRecord); }); OrderCountingRecord::query()->insert($result->toArray()); return ['resultOrders' => $result]; } public function orderCountingRecords($start = '2020-10-1', $end = '2020-11-09', $unit = '月') { $orders = $this->get($start, $end, null, $unit); $dataList = collect(); $orders->groupBy('date_target')->each(function ($items) use (&$dataList, $unit) { $counter = $items->reduce(function ($sum, $item) { return $sum + $item->amount; }, 0); $date_target = $items[0]->date_target; if ($unit == '周') { $date_target = (new DateTime())->setISODate(Str::of($date_target)->explode('-')[0], Str::of($date_target)->explode('-')[1])->format('yy-m-d'); } $dataList->push([ 'counter' => $counter, 'date_target' => $date_target, ]); }); return $dataList->sortBy("date_target"); } public function periodDateToArray($start, $end, $unit = '日') { $dataArray = []; switch ($unit) { case '日'; foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) { $dataArray[] = $item->toDateString(); } break; case '周'; foreach (Carbon::parse($start)->daysUntil($end, 1)->toArray() as $item) { $dataArray[] = $item->year . '-' . $item->week . ''; } break; case '月'; foreach (Carbon::parse($start)->monthsUntil($end, 1)->toArray() as $item) { $dataArray[] = $item->year . '-' . $item->month . ''; } break; case '年'; foreach (Carbon::parse($start)->yearsUntil($end, 1)->toArray() as $item) { $dataArray[] = $item->year . '-' . $item->month . ''; } break; default: break; } return $dataArray; } /** * @param $ownerIds * @return array */ public function getCountingOwnerIds($ownerIds = null): array { $user = auth()->user(); /** @var UserService $userService */ $userService = app('UserService'); $permittingOwnerIds = $userService->getPermittingOwnerIds($user); if (!$ownerIds) { return $permittingOwnerIds; } return Cache::remember( 'PermittingOwnerIds' . '_' . auth()->user()->id . '_' . implode('_', $ownerIds), config('cache.rarelyChange'), function () use ($ownerIds, $permittingOwnerIds) { /** @var User $user */ return array_intersect($ownerIds, $permittingOwnerIds); }); } /** * @param $targetOwnerIdsUnderDates * @return \Illuminate\Database\Eloquent\Builder[]|Collection */ private function getCreateByDatabaseUnitDay($targetOwnerIdsUnderDates) { $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"); foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) { $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) { $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', $dateStr); }); } return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get(); } private function getCreateByDatabaseUnitWeek($targetOwnerIdsUnderDates) { $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"); foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) { $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) { $dateStr = (new DateTime())->setISODate(Str::of($dateStr)->explode('-')[0], Str::of($dateStr)->explode('-')[1])->format('yy-m-d'); $query->whereIn('owner_id', $ownerIds)->whereDate('created_at', '>=', $dateStr)->whereDate('created_at', '<', Carbon::parse($dateStr)->addWeek()->toDateString()); }); } return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get(); } private function getCreateByDatabaseUnitMounth($targetOwnerIdsUnderDates) { $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"); foreach ($targetOwnerIdsUnderDates as $dateStr => $ownerIds) { $orderSqlBuilder->orWhere(function ($query) use ($ownerIds, $dateStr) { $year = Str::of($dateStr)->explode('-')[0]; $month = Str::of($dateStr)->explode('-')[1]; $query->whereIn('owner_id', $ownerIds)->whereMonth('created_at', $month)->whereYear('created_at', $year); }); } return $orderSqlBuilder->groupBy(['owner_id', 'warehouse_id', 'shop_id', 'logistic_id', 'date_target'])->get(); } }