鲜花2.0-定时任务统计每日库存报表数据+库存扣减完成

This commit is contained in:
杨建炊 2024-07-31 17:58:06 +08:00
parent ab03594786
commit dba30f1168
9 changed files with 208 additions and 14 deletions

View File

@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands;
use App\Models\BusinessOrderItem;
use App\Models\DailyReport;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\LossRecords;
use App\Models\PurchaseRecords;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class DailyStockRecordReport extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'daily:report:stock_record';
/**
* The console command description.
*
* @var string
*/
protected $description = '每日商品库存记录';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$date = Carbon::yesterday()->format('Y-m-d');
$startDateTime = Carbon::parse($date)->startOfDay()->toDateTimeString();
$endDateTime = Carbon::parse($date)->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(goods_number-already_cancel_number) as goods_total"))
->whereBetween("business_order_items.created_at", [$startDateTime, $endDateTime])
->where("business_order_items.cancel_status", "=", 0)
->groupBy('external_sku_id')->get()->pluck(null, "external_sku_id")->toArray();
//统计采购单数量
$purchaseRecords = PurchaseRecords::query()
->select(DB::raw("sum(num) as arrived_today_num"), "external_sku_id")
->whereBetween("created_at", [$startDateTime, $endDateTime])
->groupBy("external_sku_id")->get()->pluck(null, "external_sku_id")->toArray();
//统计报损数量
$lossRecords = LossRecords::query()
->select(DB::raw("sum(num) as loss_num"), "external_sku_id")
->whereBetween("created_at", [$startDateTime, $endDateTime])
->groupBy("external_sku_id")->get()->pluck(null, "external_sku_id")->toArray();
Log::info("{$date}每日库存记录", ["orderItems" => $orderItems
, "purchaseRecords" => $purchaseRecords, "lossRecords" => $lossRecords]);
$needUpdateExternalSkuIds = array_merge(array_keys($orderItems), array_keys($purchaseRecords), array_keys($lossRecords));
//开始更新数据
if (!empty($needUpdateExternalSkuIds)) {
$needUpdateSkuIdsMap = GoodsSku::query()->whereIn("external_sku_id", $needUpdateExternalSkuIds)->pluck("external_sku_id", 'id')->toArray();
collect($needUpdateSkuIdsMap)->each(function ($externalSkuId,$skuId) use ($date, $orderItems, $purchaseRecords, $lossRecords) {
$record = DailyStockRecord::query()->firstOrNew([
'sku_id' => $skuId,
'day' => $date,
]);
$record->arrived_today_num = !empty($purchaseRecords[$externalSkuId]["arrived_today_num"])
? $purchaseRecords[$externalSkuId]["arrived_today_num"] : 0;
$record->loss_num = !empty($lossRecords[$externalSkuId]["loss_num"])
? $lossRecords[$externalSkuId]["loss_num"] : 0;
$record->order_goods_num = !empty($orderItems[$externalSkuId]["goods_total"])
? $orderItems[$externalSkuId]["goods_total"] : 0;
$record->save();
});
}
}
}

View File

@ -3,10 +3,16 @@
namespace App\Http\Controllers\DataCenter;
use App\Http\Controllers\Controller;
use App\Http\Enum\StaticTypeEnum;
use App\Http\Resources\DailySalesReportResource;
use App\Models\BusinessOrderItem;
use App\Models\DailySalesReport;
use App\Models\GoodsSku;
use App\Utils\FormatUtils;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class DataCenterController extends Controller
{
@ -37,4 +43,48 @@ class DataCenterController extends Controller
return DailySalesReportResource::collection($dailySalesReports);
}
/**
* 销售报表
* @param Request $request
* @return void
*/
public function skuSalesReport(Request $request)
{
//获取所有参数
$allParams = $request->all();
//进行校验验证
$validator = Validator::make($allParams, [
'type' => 'required|integer', //1表示今日
'start_day' => 'sometimes|string',
'end_day' => 'sometimes|string',
'title' => 'sometimes|string'
]);
if ($validator->fails()) {
//校验失败返回异常
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
if (StaticTypeEnum::TODAY == $allParams->type) {
//实时统计
$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"))
->where("business_order_items.created_at", ">",Carbon::now()->startOfDay()->toDateTimeString())
->where("business_order_items.cancel_status", "=", 0)
->groupBy('external_sku_id')
->orderBy("goods_total","DESC")
->paginate($request->get('per_page'));
return $orderItems;
} else {
$startTime = Carbon::parse($request->input("start_day"))->toDateTimeString();
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
}
}
}

View File

@ -63,7 +63,7 @@ class DailyStockRecordController extends Controller
$goodsSku = GoodsSku::query()->with("combinationGoods")->where('external_sku_id', "=", $request->external_sku_id)->first();
if (empty($goodsSku)) {
$this->res = [
'httpCode' => 200,
'httpCode' => 400,
'message' => '查询不到sku信息',
'errorCode' => "ERP001",
'errorMessage' => '查询不到sku信息',

View File

@ -69,7 +69,7 @@ class LossRecordController extends Controller
event(new BatchStockUpdateEvent($updateIds));
} else {
$this->res = [
'httpCode' => 200,
'httpCode' => 400,
'message' => '查询不到sku信息',
'errorCode' => "ERP001",
'errorMessage' => '查询不到sku信息',
@ -94,17 +94,15 @@ class LossRecordController extends Controller
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$goodsSku = GoodsSku::query()->where('id', "=", $id)->get();
if (!empty($goodsSku)) {
$lossRecords = LossRecords::query()->find($id);
if (!empty($lossRecords)) {
//更新記錄
$lossRecords = new LossRecords();
$lossRecords->buyer_name = $allParams['buyer_name'] ?? '';
$lossRecords->reason = $allParams['reason'] ?? '';
$lossRecords->save();
} else {
$this->res = [
'httpCode' => 200,
'httpCode' => 400,
'message' => '查询不到sku信息',
'errorCode' => "ERP001",
'errorMessage' => '查询不到sku信息',

View File

@ -75,7 +75,7 @@ class PurchaseRecordController extends Controller
event(new BatchStockUpdateEvent($updateIds));
} else {
$this->res = [
'httpCode' => 200,
'httpCode' => 400,
'message' => '查询不到sku信息',
'errorCode' => "ERP001",
'errorMessage' => '查询不到sku信息',
@ -116,7 +116,7 @@ class PurchaseRecordController extends Controller
} else {
$this->res = [
'httpCode' => 200,
'httpCode' => 400,
'message' => '查询不到sku信息',
'errorCode' => "ERP001",
'errorMessage' => '查询不到sku信息',

View File

@ -0,0 +1,11 @@
<?php
namespace App\Http\Enum;
class StaticTypeEnum
{
const TODAY = 1;
}

View File

@ -3,10 +3,13 @@
namespace App\Services\GoodSku;
use App\Events\BatchStockUpdateEvent;
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\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class GoodSkuService
@ -18,9 +21,10 @@ class GoodSkuService
*/
public function inventory(array $skusWithCombinationGoods)
{
$skusWithCombinationGoods = $this->handleSkusWithCombinationGoods($skusWithCombinationGoods);
//传进来的sku可能包含组合商品 所以这里需要事先计算好数据
$inventoryKeyBySkuIdMap = collect($skusWithCombinationGoods)->where('is_combination', "=", 0)
->pluck("inventory", "sku_id")->toArray();
->pluck("inventory", "id")->toArray();
//计算组合商品
foreach ($skusWithCombinationGoods as $sku) {
if (!empty($sku['is_combination'])) {
@ -28,7 +32,7 @@ class GoodSkuService
if (empty($inventoryKeyBySkuIdMap[$combinationGoods["item_id"]])) {
//没有盘点到的sku需要在原先的sku库存
$inventoryKeyBySkuIdMap[$combinationGoods["item_id"]] = GoodsSku::query()
->where('id', $combinationGoods["item_id"])->pluck('stock')->first()??0;
->where('id', $combinationGoods["item_id"])->pluck('stock')->first() ?? 0;
}
$inventoryKeyBySkuIdMap[$combinationGoods["item_id"]] += $combinationGoods['item_num'] * $sku['inventory'];
@ -50,7 +54,6 @@ class GoodSkuService
$record->inventory = $totalInventory;
$record->inventory_time = $dateTime;
$record->save();
//查询sku当前未发货的数量 目前数据看着有问题暂不操作
//库存修改 盘点是直接覆盖
GoodsSku::query()->where('id', $skuId)->update([
@ -62,7 +65,36 @@ class GoodSkuService
event(new BatchStockUpdateEvent($updateIds));
}
public static function computeSkuStock(array $goodsSkuItem, array $v): array
/**
* 库存盘点 需要扣减未发货未取消的订单数据
* 目前只查询了7日内的数据
* @param array $skusWithCombinationGoods
* @return \Illuminate\Support\Collection
*/
public function handleSkusWithCombinationGoods(array $skusWithCombinationGoods){
//查询sku当前未发货的数量 需要扣减
$externalSkuIds = collect($skusWithCombinationGoods)->pluck("external_sku_id")->toArray();
//默认只查7天内未发货的数据
$startTime = Carbon::now()->subDays(7)->startOfDay()->toDateTimeString();
$unshippedDataCollect = BusinessOrderItem::query()
->leftJoin("business_orders as b", "business_order_id", "=", "b.id")
->select("external_sku_id", DB::raw("sum(goods_number) as goods_total"), DB::raw("sum(already_cancel_number) as cancel_total"))
->whereIn("external_sku_id", $externalSkuIds)->where("b.shipping_status", "=", 0)
->where("business_order_items.created_at", ">=", $startTime)->where("business_order_items.cancel_status", "=", 0)
->groupBy('external_sku_id')->get()->toArray();
$unshippedData = collect($unshippedDataCollect)->pluck(null,"external_sku_id")->toArray();
Log::info("7日内未发货数据", $unshippedData);
return collect($skusWithCombinationGoods)->map(function ($v) use ($unshippedData) {
if (!empty($unshippedData[$v['external_sku_id']])) {
$v['inventory'] = $v['inventory'] - $unshippedData[$v['external_sku_id']]['goods_total']
+ $unshippedData[$v['external_sku_id']]['cancel_total'];
}
return $v;
})->toArray();
}
public static function computeSkuStock(array $goodsSkuItem, array $v)
{
$updateIds = [];
Log::info("库存更新前完整商品信息", $goodsSkuItem);

View File

@ -85,6 +85,10 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::resource('supplier/loss_record', 'Supplier\LossRecordController',['only' => ['index', 'store','update']]);
//仓库管理-盘点
Route::resource('supplier/daily_stock_record', 'Supplier\DailyStockRecordController',['only' => ['index', 'store']]);
// 数据中心 销售报表
Route::get('data_center/sku_sales_report', [DataCenterController::class, 'skuSalesReport'])->name('sku_sales_report.index');
});
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');

View File

@ -4,6 +4,8 @@
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrderItem;
use App\Models\GoodsSku;
use App\Services\Business\BusinessFactory;
use App\Utils\DateTimeUtils;
use Illuminate\Support\Facades\Log;
use Tests\TestCase;
@ -18,7 +20,12 @@ class BusinessOrderUpdateTest extends TestCase
*/
public function testBasicTest()
{
// $shop = new \App\Models\Shop();
// $shop->id=19;
// $shop->access_token="7e00e77428cf45348cb1ca190dc769670377bd0c";
// $endTime = DateTimeUtils::getMicroTime();
// $beginTime = $endTime - 63000;
// BusinessFactory::init()->make("快团团")->setShop($shop)->downloadOrdersAndSave($beginTime, $endTime, 'increment');
}
}