鲜花2.0-定时任务统计每日库存报表数据+库存扣减完成
This commit is contained in:
parent
ab03594786
commit
dba30f1168
92
app/Console/Commands/DailyStockRecordReport.php
Normal file
92
app/Console/Commands/DailyStockRecordReport.php
Normal 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,10 +3,16 @@
|
|||||||
namespace App\Http\Controllers\DataCenter;
|
namespace App\Http\Controllers\DataCenter;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Enum\StaticTypeEnum;
|
||||||
use App\Http\Resources\DailySalesReportResource;
|
use App\Http\Resources\DailySalesReportResource;
|
||||||
|
use App\Models\BusinessOrderItem;
|
||||||
use App\Models\DailySalesReport;
|
use App\Models\DailySalesReport;
|
||||||
|
use App\Models\GoodsSku;
|
||||||
use App\Utils\FormatUtils;
|
use App\Utils\FormatUtils;
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class DataCenterController extends Controller
|
class DataCenterController extends Controller
|
||||||
{
|
{
|
||||||
@ -37,4 +43,48 @@ class DataCenterController extends Controller
|
|||||||
|
|
||||||
return DailySalesReportResource::collection($dailySalesReports);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ class DailyStockRecordController extends Controller
|
|||||||
$goodsSku = GoodsSku::query()->with("combinationGoods")->where('external_sku_id', "=", $request->external_sku_id)->first();
|
$goodsSku = GoodsSku::query()->with("combinationGoods")->where('external_sku_id', "=", $request->external_sku_id)->first();
|
||||||
if (empty($goodsSku)) {
|
if (empty($goodsSku)) {
|
||||||
$this->res = [
|
$this->res = [
|
||||||
'httpCode' => 200,
|
'httpCode' => 400,
|
||||||
'message' => '查询不到sku信息',
|
'message' => '查询不到sku信息',
|
||||||
'errorCode' => "ERP001",
|
'errorCode' => "ERP001",
|
||||||
'errorMessage' => '查询不到sku信息',
|
'errorMessage' => '查询不到sku信息',
|
||||||
|
|||||||
@ -69,7 +69,7 @@ class LossRecordController extends Controller
|
|||||||
event(new BatchStockUpdateEvent($updateIds));
|
event(new BatchStockUpdateEvent($updateIds));
|
||||||
} else {
|
} else {
|
||||||
$this->res = [
|
$this->res = [
|
||||||
'httpCode' => 200,
|
'httpCode' => 400,
|
||||||
'message' => '查询不到sku信息',
|
'message' => '查询不到sku信息',
|
||||||
'errorCode' => "ERP001",
|
'errorCode' => "ERP001",
|
||||||
'errorMessage' => '查询不到sku信息',
|
'errorMessage' => '查询不到sku信息',
|
||||||
@ -94,17 +94,15 @@ class LossRecordController extends Controller
|
|||||||
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
|
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
|
||||||
return response($this->res, $this->res['httpCode']);
|
return response($this->res, $this->res['httpCode']);
|
||||||
}
|
}
|
||||||
$goodsSku = GoodsSku::query()->where('id', "=", $id)->get();
|
$lossRecords = LossRecords::query()->find($id);
|
||||||
if (!empty($goodsSku)) {
|
if (!empty($lossRecords)) {
|
||||||
//更新記錄
|
//更新記錄
|
||||||
$lossRecords = new LossRecords();
|
|
||||||
$lossRecords->buyer_name = $allParams['buyer_name'] ?? '';
|
$lossRecords->buyer_name = $allParams['buyer_name'] ?? '';
|
||||||
$lossRecords->reason = $allParams['reason'] ?? '';
|
$lossRecords->reason = $allParams['reason'] ?? '';
|
||||||
$lossRecords->save();
|
$lossRecords->save();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->res = [
|
$this->res = [
|
||||||
'httpCode' => 200,
|
'httpCode' => 400,
|
||||||
'message' => '查询不到sku信息',
|
'message' => '查询不到sku信息',
|
||||||
'errorCode' => "ERP001",
|
'errorCode' => "ERP001",
|
||||||
'errorMessage' => '查询不到sku信息',
|
'errorMessage' => '查询不到sku信息',
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class PurchaseRecordController extends Controller
|
|||||||
event(new BatchStockUpdateEvent($updateIds));
|
event(new BatchStockUpdateEvent($updateIds));
|
||||||
} else {
|
} else {
|
||||||
$this->res = [
|
$this->res = [
|
||||||
'httpCode' => 200,
|
'httpCode' => 400,
|
||||||
'message' => '查询不到sku信息',
|
'message' => '查询不到sku信息',
|
||||||
'errorCode' => "ERP001",
|
'errorCode' => "ERP001",
|
||||||
'errorMessage' => '查询不到sku信息',
|
'errorMessage' => '查询不到sku信息',
|
||||||
@ -116,7 +116,7 @@ class PurchaseRecordController extends Controller
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->res = [
|
$this->res = [
|
||||||
'httpCode' => 200,
|
'httpCode' => 400,
|
||||||
'message' => '查询不到sku信息',
|
'message' => '查询不到sku信息',
|
||||||
'errorCode' => "ERP001",
|
'errorCode' => "ERP001",
|
||||||
'errorMessage' => '查询不到sku信息',
|
'errorMessage' => '查询不到sku信息',
|
||||||
|
|||||||
11
app/Http/Enum/StaticTypeEnum.php
Normal file
11
app/Http/Enum/StaticTypeEnum.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Enum;
|
||||||
|
|
||||||
|
|
||||||
|
class StaticTypeEnum
|
||||||
|
{
|
||||||
|
|
||||||
|
const TODAY = 1;
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,10 +3,13 @@
|
|||||||
namespace App\Services\GoodSku;
|
namespace App\Services\GoodSku;
|
||||||
|
|
||||||
use App\Events\BatchStockUpdateEvent;
|
use App\Events\BatchStockUpdateEvent;
|
||||||
|
use App\Models\BusinessOrderItem;
|
||||||
use App\Models\CombinationGood;
|
use App\Models\CombinationGood;
|
||||||
use App\Models\DailyStockRecord;
|
use App\Models\DailyStockRecord;
|
||||||
use App\Models\GoodsSku;
|
use App\Models\GoodsSku;
|
||||||
use App\Utils\DateTimeUtils;
|
use App\Utils\DateTimeUtils;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class GoodSkuService
|
class GoodSkuService
|
||||||
@ -18,9 +21,10 @@ class GoodSkuService
|
|||||||
*/
|
*/
|
||||||
public function inventory(array $skusWithCombinationGoods)
|
public function inventory(array $skusWithCombinationGoods)
|
||||||
{
|
{
|
||||||
|
$skusWithCombinationGoods = $this->handleSkusWithCombinationGoods($skusWithCombinationGoods);
|
||||||
//传进来的sku可能包含组合商品 所以这里需要事先计算好数据
|
//传进来的sku可能包含组合商品 所以这里需要事先计算好数据
|
||||||
$inventoryKeyBySkuIdMap = collect($skusWithCombinationGoods)->where('is_combination', "=", 0)
|
$inventoryKeyBySkuIdMap = collect($skusWithCombinationGoods)->where('is_combination', "=", 0)
|
||||||
->pluck("inventory", "sku_id")->toArray();
|
->pluck("inventory", "id")->toArray();
|
||||||
//计算组合商品
|
//计算组合商品
|
||||||
foreach ($skusWithCombinationGoods as $sku) {
|
foreach ($skusWithCombinationGoods as $sku) {
|
||||||
if (!empty($sku['is_combination'])) {
|
if (!empty($sku['is_combination'])) {
|
||||||
@ -28,7 +32,7 @@ class GoodSkuService
|
|||||||
if (empty($inventoryKeyBySkuIdMap[$combinationGoods["item_id"]])) {
|
if (empty($inventoryKeyBySkuIdMap[$combinationGoods["item_id"]])) {
|
||||||
//没有盘点到的sku需要在原先的sku库存
|
//没有盘点到的sku需要在原先的sku库存
|
||||||
$inventoryKeyBySkuIdMap[$combinationGoods["item_id"]] = GoodsSku::query()
|
$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'];
|
$inventoryKeyBySkuIdMap[$combinationGoods["item_id"]] += $combinationGoods['item_num'] * $sku['inventory'];
|
||||||
@ -50,7 +54,6 @@ class GoodSkuService
|
|||||||
$record->inventory = $totalInventory;
|
$record->inventory = $totalInventory;
|
||||||
$record->inventory_time = $dateTime;
|
$record->inventory_time = $dateTime;
|
||||||
$record->save();
|
$record->save();
|
||||||
//查询sku当前未发货的数量 目前数据看着有问题暂不操作
|
|
||||||
|
|
||||||
//库存修改 盘点是直接覆盖
|
//库存修改 盘点是直接覆盖
|
||||||
GoodsSku::query()->where('id', $skuId)->update([
|
GoodsSku::query()->where('id', $skuId)->update([
|
||||||
@ -62,7 +65,36 @@ class GoodSkuService
|
|||||||
event(new BatchStockUpdateEvent($updateIds));
|
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 = [];
|
$updateIds = [];
|
||||||
Log::info("库存更新前完整商品信息", $goodsSkuItem);
|
Log::info("库存更新前完整商品信息", $goodsSkuItem);
|
||||||
|
|||||||
@ -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/loss_record', 'Supplier\LossRecordController',['only' => ['index', 'store','update']]);
|
||||||
//仓库管理-盘点
|
//仓库管理-盘点
|
||||||
Route::resource('supplier/daily_stock_record', 'Supplier\DailyStockRecordController',['only' => ['index', 'store']]);
|
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('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
|
||||||
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');
|
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
use App\Models\BusinessGoodsSku;
|
use App\Models\BusinessGoodsSku;
|
||||||
use App\Models\BusinessOrderItem;
|
use App\Models\BusinessOrderItem;
|
||||||
use App\Models\GoodsSku;
|
use App\Models\GoodsSku;
|
||||||
|
use App\Services\Business\BusinessFactory;
|
||||||
|
use App\Utils\DateTimeUtils;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
@ -18,7 +20,12 @@ class BusinessOrderUpdateTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testBasicTest()
|
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');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user