type) { //实时统计 sku维度 return static::skuSaleStatisticsByToday($request); } else { //历史数据查询 return static::skuSaleStatisticsByHistory($request); } } public static function skuSaleStatisticsByToday(Request $request) { [$startTime, $endTime] = static::getTimeRange($request); $build = BusinessOrderItem::query(); if (!empty($request->sku_id)) { $externalSkuId = GoodsSku::query()->where("id", "=", $request->sku_id) ->pluck("external_sku_id")->first(); if (!empty($externalSkuId)) { $build->where("external_sku_id", "=", $externalSkuId); } else { return []; } } $orderItems = $build ->leftJoin("business_orders as b", "business_order_id", "=", "b.id") ->select("business_order_items.external_sku_id" , DB::raw("sum(CASE WHEN b.shipping_status>0 THEN goods_number-already_cancel_number ELSE 0 END) as shipping_num") , DB::raw("sum(CASE WHEN b.shipping_status=0 THEN goods_number-already_cancel_number ELSE 0 END) as unshipping_num") , DB::raw("sum(goods_number-already_cancel_number) as goods_total") , DB::raw("ROUND(sum(goods_amount) / 100,2) as goods_total_amount")) ->whereBetween("business_order_items.created_at", [$startTime, $endTime]) ->where("external_sku_id", "!=", "") ->where("business_order_items.cancel_status", "=", 0) ->groupBy('external_sku_id') ->orderBy("goods_total", "DESC") ->paginate($request->get('per_page')); if (!empty($orderItems->items())) { $externalSkuIds = collect($orderItems->items())->pluck("external_sku_id")->toArray(); $goodsSkus = GoodsSku::query()->whereIn("external_sku_id", $externalSkuIds) ->select("id", "title", "name", "stock", "sale_stock", "status", "external_sku_id")->get() ->pluck(null, "id")->toArray(); return static::addSaleDataToGoodsSku($goodsSkus, $orderItems); } return $orderItems; } public static function skuSaleStatisticsByHistory(Request $request) { [$startTime, $endTime] = static::getTimeRange($request); $build = DailyStockRecord::query(); if (!empty($request->sku_id)) { $build->where("sku_id", "=", $request->sku_id); } $dailyRecord = $build->select("sku_id", DB::raw("sum(order_goods_num) as goods_total") , DB::raw("sum(order_total_amount) as goods_total_amount")) ->whereBetween("created_at", [$startTime, $endTime]) ->groupBy("sku_id") ->having(DB::raw("sum(order_goods_num)"), ">", 0) ->orderBy("goods_total", "DESC") ->paginate($request->get('per_page')); $skuIds = collect($dailyRecord->items())->pluck('sku_id')->toArray(); $goodsSkusMapKeyBySkuId = GoodsSku::query()->select("id", "title", "name", "stock", "sale_stock" , "status", "external_sku_id")->whereIn("id", $skuIds) ->get()->pluck(null, "id")->toArray(); $dailyRecord->getCollection()->map(function ($v) use ($goodsSkusMapKeyBySkuId) { if (!empty($goodsSkusMapKeyBySkuId[$v['sku_id']])) { foreach ($goodsSkusMapKeyBySkuId[$v['sku_id']] as $key => $val) { $v->$key = $val; } } else { //出现异常的skuid $v->title = "未知商品"; $v->name = "未知商品"; $v->stock = 0; $v->sale_stock = 0; $v->status = "下架"; $v->id = 0; } }); return $dailyRecord; } public static function addSaleDataToGoodsSku($goodsSku, $orderItems) { $skuIds = collect($goodsSku)->pluck("id")->toArray(); //查询8天内-昨天的数据 $startTime = Carbon::now()->subDays(8)->startOfDay()->toDateTimeString(); $endTime = Carbon::yesterday()->endOfDay()->toDateTimeString(); $dailyRecord = DailyStockRecord::query()->whereIn("sku_id", $skuIds) ->whereBetween("day", [$startTime, $endTime]) ->get()->toArray(); $dailyRecordGroupBySkuId = collect($dailyRecord)->groupBy("sku_id")->toArray(); Log::info("dailyRecordGroupBySkuId", $dailyRecordGroupBySkuId); $combineGoodsSkus = collect($goodsSku)->map(function ($v) use ($dailyRecordGroupBySkuId, $orderItems) { $v['yesterday_avg_num'] = round(collect($dailyRecordGroupBySkuId[$v['id']] ?? [])->sortByDesc("day") ->take(1)->avg("order_goods_num") ?? 0, 2); $v['three_day_avg_num'] = round(collect($dailyRecordGroupBySkuId[$v['id']] ?? [])->sortByDesc("day") ->take(3)->avg("order_goods_num") ?? 0, 2); $v['seven_day_avg_num'] = round(collect($dailyRecordGroupBySkuId[$v['id']] ?? [])->sortByDesc("day") ->take(7)->avg("order_goods_num") ?? 0, 2); return $v; })->pluck(null, "external_sku_id")->toArray(); Log::info("combineGoodsSkus", $combineGoodsSkus); $orderItems->getCollection()->map(function ($v) use ($combineGoodsSkus) { if (!empty($combineGoodsSkus[$v['external_sku_id']])) { foreach ($combineGoodsSkus[$v['external_sku_id']] as $key => $val) { $v->$key = $val; } } else { //出现异常售卖的编码 $v->title = "未知商品"; $v->name = "未知商品"; $v->stock = 0; $v->sale_stock = 0; $v->status = "下架"; $v->yesterday_avg_num = 0; $v->three_day_avg_num = 0; $v->id = 0; $v->seven_day_avg_num = 0; } }); return $orderItems; } public static function spuSaleStatistics(Request $request) { //spu 基本就是全统计了 if (StaticTypeEnum::TODAY == $request->type) { return static::spuSaleStatisticsByToday($request); } else { //统计历史数据 这里走缓存 return static::spuSaleStatisticsByHistoryCache($request); } } public static function getTimeRange(Request $request) { if (!empty($request->input("start_time")) && !empty($request->input("start_time"))) { $startTime = Carbon::parse($request->input("start_time"))->toDateTimeString(); $endTime = Carbon::parse($request->input("end_time"))->toDateTimeString(); } else { $startTime = Carbon::parse($request->input("start_day"))->toDateTimeString(); $endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString(); } return [$startTime, $endTime]; } public static function spuSaleStatisticsByToday(Request $request) { [$startTime, $endTime] = static::getTimeRange($request); //实时统计 sku维度 $orderItems = BusinessOrderItem::query() ->leftJoin("business_orders as b", "business_order_id", "=", "b.id") ->select("business_order_items.external_sku_id" , DB::raw("sum(CASE WHEN b.shipping_status>0 THEN goods_number-already_cancel_number ELSE 0 END) as shipping_num") , DB::raw("sum(CASE WHEN b.shipping_status=0 THEN goods_number-already_cancel_number ELSE 0 END) as unshipping_num") , DB::raw("sum(goods_number-already_cancel_number) as goods_total") , DB::raw("ROUND(sum(goods_amount) / 100,2) as goods_total_amount")) ->whereBetween("business_order_items.created_at", [$startTime, $endTime]) ->where("external_sku_id", "!=", "") ->where("business_order_items.cancel_status", "=", 0) ->groupBy('external_sku_id')->get()->toArray(); $externalSkuIds = collect($orderItems)->pluck("external_sku_id")->toArray(); $orderItemsKeyByExternalSkuId = collect($orderItems)->pluck(null, "external_sku_id")->toArray(); $goodsSkuWithTypes = GoodsSku::query() ->Join("goods", "goods_id", "=", "goods.id") ->Join("goods_types", "goods.type_id", "=", "goods_types.id") ->whereIn("external_sku_id", $externalSkuIds) ->select("goods_skus.id", "goods_types.id as type_id", "goods_types.name", "external_sku_id", "stock", "sale_stock")->get() ->toArray(); return collect($goodsSkuWithTypes)->map(function ($v) use ($orderItemsKeyByExternalSkuId) { if (!empty($orderItemsKeyByExternalSkuId[$v['external_sku_id']])) { return array_merge($v, $orderItemsKeyByExternalSkuId[$v['external_sku_id']]); } })->filter()->values()->groupBy('type_id')->map(function ($v, $key) { return [ "type_id" => $key, "type_name" => $v[0]['name'] ?? '', "stock" => $v->sum("stock"), "sale_stock" => $v->sum("sale_stock"), "shipping_num" => $v->sum("shipping_num"), "unshipping_num" => $v->sum("unshipping_num"), "goods_total" => $v->sum("goods_total"), "goods_total_amount" => $v->sum("goods_total_amount"), ]; })->values()->toArray(); } /** * 通过历史报表统计spu数据-缓存 * @param Request $request * @return mixed */ public static function spuSaleStatisticsByHistoryCache(Request $request) { [$startTime, $endTime] = static::getTimeRange($request); $cacheKey = CacheKeyEnum::SPU_STATISTIC_BY_DATE . $request->input("start_day") . "_" . $request->input("end_day"); $expireTime = Carbon::now()->addHour(); return Cache::remember($cacheKey, $expireTime, function () use ($startTime, $endTime) { return static::spuSaleStatisticsByHistory($startTime, $endTime); }); } /** * 通过历史报表统计spu数据 * @param $startTime * @param $endTime * @return array */ public static function spuSaleStatisticsByHistory($startTime, $endTime) { $dailyAllRecord = DailyStockRecord::query() ->select("sku_id", DB::raw("sum(order_goods_num) as goods_total") , DB::raw("sum(order_total_amount) as goods_total_amount")) ->whereBetween("day", [$startTime, $endTime]) ->groupBy("sku_id") ->having(DB::raw("sum(order_goods_num)"), ">", 0) ->get()->toArray(); $skuIds = collect($dailyAllRecord)->pluck('sku_id')->toArray(); $dailyRecordMapKeyBySkuId = collect($dailyAllRecord)->pluck(null, 'sku_id')->toArray(); $goodsSkuWithTypes = GoodsSku::query() ->Join("goods", "goods_id", "=", "goods.id") ->Join("goods_types", "goods.type_id", "=", "goods_types.id") ->select("goods_skus.id", "goods_types.id as type_id", "goods_types.name", "external_sku_id", "stock", "sale_stock") ->whereIn("goods_skus.id", $skuIds) ->get()->toArray(); return collect($goodsSkuWithTypes)->map(function ($v) use ($dailyRecordMapKeyBySkuId) { if (!empty($dailyRecordMapKeyBySkuId[$v['id']])) { return array_merge($v, $dailyRecordMapKeyBySkuId[$v['id']]); } })->filter()->values()->groupBy('type_id')->map(function ($v, $key) { return [ "type_id" => $key, "type_name" => $v[0]['name'] ?? '', "stock" => $v->sum("stock"), "sale_stock" => $v->sum("sale_stock"), "goods_total" => $v->sum("goods_total"), "goods_total_amount" => $v->sum("goods_total_amount"), ]; })->values()->toArray(); } public static function gmvStatistics(Request $request) { if (StaticTypeEnum::TODAY == $request->type) { [$startTime, $endTime] = static::getTimeRange($request); $build = BusinessOrderItem::query(); if (!empty($request->sku_id)) { $externalSkuId = GoodsSku::query()->where("id", "=", $request->sku_id) ->pluck("external_sku_id")->first(); if (!empty($externalSkuId)) { $build->where("external_sku_id", "=", $externalSkuId); } else { return []; } } $orderItems = $build->select("business_order_items.external_sku_id" , "goods_number", "already_cancel_number", "goods_amount", "created_at") ->whereBetween("business_order_items.created_at", [$startTime, $endTime]) ->where("business_order_items.cancel_status", "=", 0) ->get()->toArray(); $interval = $request->input("interval", 30); return collect($orderItems)->groupBy(function ($v) use ($startTime, $interval) { $diff = Carbon::parse($v['created_at'])->diffInMinutes(Carbon::parse($startTime)); return (int)floor($diff / $interval); })->map(function ($v, $key) use ($startTime, $interval) { return [ "sort_key" => $key, "interval" => $interval, "time_start" => Carbon::parse($startTime)->addMinutes($key * $interval)->toTimeString(), "time_end" => Carbon::parse($startTime)->addMinutes(($key + 1) * $interval)->toTimeString(), "goods_total" => $v->sum("goods_number") - $v->sum("already_cancel_number"), "goods_total_amount" => round($v->sum("goods_amount") / 100, 2), ]; })->sort()->values()->toArray(); } else { //gmv 统计历史数据 [$startTime, $endTime] = static::getTimeRange($request); $build = DailyStockRecord::query(); if (!empty($request->sku_id)) { $build->where("sku_id", "=", $request->sku_id); } return $build->select("day", DB::raw("sum(order_total_amount) as goods_total_amount") , DB::raw("sum(order_goods_num) as goods_total")) ->whereBetween("day", [$startTime, $endTime]) ->groupBy("day")->orderBy("day") ->get()->toArray(); } } public static function lossRecordStatistics(Request $request) { $startTime = Carbon::parse($request->input("start_time"))->toDateTimeString(); $endTime = Carbon::parse($request->input("end_time"))->toDateTimeString(); $build = LossRecords::query(); if (!empty($request->sku_id)) { $externalSkuId = GoodsSku::query()->where("id", "=", $request->sku_id) ->pluck("external_sku_id")->first(); if (!empty($externalSkuId)) { $build->where("external_sku_id", "=", $externalSkuId); } else { return []; } } return $build->select("date", DB::raw("sum(num) as total_num") , DB::raw("sum(num*cost) as total_loss_amount")) ->whereBetween("date", [$startTime, $endTime]) ->groupBy("date")->orderBy("date") ->get()->toArray(); } }