mirror of
https://gitee.com/hzchunfen/erp.git
synced 2025-12-01 06:30:49 +00:00
287 lines
14 KiB
PHP
287 lines
14 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Service;
|
|
|
|
use App\Events\BatchStockUpdateEvent;
|
|
use App\Http\Enum\CacheKeyEnum;
|
|
use App\Http\Enum\StaticTypeEnum;
|
|
use App\Models\BusinessOrderItem;
|
|
use App\Models\CombinationGood;
|
|
use App\Models\DailyStockRecord;
|
|
use App\Models\GoodsSku;
|
|
use App\Utils\DateTimeUtils;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
class SaleDataService
|
|
{
|
|
|
|
public static function saleStatistics(Request $request)
|
|
{
|
|
if (StaticTypeEnum::TODAY == $request->type) {
|
|
//实时统计 sku维度
|
|
return static::skuSaleStatisticsByToday($request);
|
|
} else {
|
|
//历史数据查询
|
|
return static::skuSaleStatisticsByHistory($request);
|
|
}
|
|
}
|
|
|
|
public static function skuSaleStatisticsByToday(Request $request)
|
|
{
|
|
$startTime = Carbon::parse($request->input("start_day"))->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
$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')
|
|
->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 = Carbon::parse($request->input("start_day"))->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
$dailyRecord = 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("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("created_at", [$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 spuSaleStatisticsByToday(Request $request)
|
|
{
|
|
$startTime = Carbon::parse($request->input("start_day"))->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
//实时统计 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 = Carbon::parse($request->input("start_day"))->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
$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("created_at", [$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 = Carbon::parse($request->input("start_day"))->startOfDay()->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
$orderItems = BusinessOrderItem::query()
|
|
->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 = Carbon::parse($request->input("start_day"))->toDateTimeString();
|
|
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
|
|
return DailyStockRecord::query()
|
|
->select("day", DB::raw("sum(order_total_amount) as goods_total_amount")
|
|
, DB::raw("sum(order_goods_num) as goods_total"))
|
|
->whereBetween("created_at", [$startTime, $endTime])
|
|
->groupBy("day")->orderBy("day")
|
|
->get()->toArray();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|