| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- <?php
- namespace App\Services;
- use App\Order;
- use App\OrderCountingRecord;
- use Carbon\Carbon;
- use DateTime;
- use Illuminate\Database\Eloquent\Collection;
- use Illuminate\Support\Facades\Cache;
- use App\User;
- use Illuminate\Support\Str;
- class OrderCountingRecordService
- {
- /** @var $ownerService OwnerService */
- private $ownerService = null;
- function __construct()
- {
- $this->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();
- }
- }
|