鲜花2.0-采购单导入

This commit is contained in:
杨建炊 2024-07-26 17:48:07 +08:00
parent 3ac66d6d63
commit 3b61176cda
13 changed files with 459 additions and 267 deletions

View File

@ -44,24 +44,16 @@ class BusinessOrdersUpdate
return false;
}
$stock = $this->goodsSku->stock + $this->num;
if (0 >= $stock) {
$saleStock = $this->goodsSku->sale_stock + $this->num;
if (0 >= $saleStock) {
$this->goodsSku->status = GoodsSku::$STATUS_DOWN;
} else {
$this->goodsSku->status = GoodsSku::$STATUS_ON_SALE;
}
// 今日到货 + 1T 大于20,且当前剩余库存小于4时 直接下架
$arrivedTodayNum = DailyStockRecord::query()
->where('day', DateTimeUtils::getToday())
->where('sku_id', $this->goodsSku->id)
->value('arrived_today_num');
if (20 < $arrivedTodayNum + $this->goodsSku->yesterday_num && 4 > $stock) {
$this->goodsSku->status = GoodsSku::$STATUS_DOWN;
$stock = 0;
}
$this->goodsSku->sale_stock = $saleStock;
$this->goodsSku->stock = $stock;
Log::info("sku 业务订单库存更新",(array)$this->goodsSku);
$this->goodsSku->save();
}

View File

@ -17,6 +17,8 @@ use App\Models\DeveloperConfig;
use App\Models\Goods;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Services\GoodSku\GoodSkuService;
use App\Services\Ship\WayBillService;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Carbon\Carbon;
@ -219,7 +221,7 @@ class GoodsSkusController extends Controller
public function batchUpdate(Request $request)
{
$appendRules = [
'updateType' => ['required', 'string', Rule::in(['newest', 'inventory', 'stock'])],
'updateType' => ['required', 'string', Rule::in(['newest', 'inventory', 'stock',"stockManage"])],
'skus' => ['required', 'array'],
'skus.*.id' => [
'required',
@ -238,6 +240,52 @@ class GoodsSkusController extends Controller
return $this->$function($request);
}
/**
* 新版本运营管理 主要修改在线库存和成本价(修订) 看看是否需要单独提供修改
*
* @param $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
private function stockManage($request)
{
DB::beginTransaction();
try {
$logs = [];
foreach ($request->skus as $sku) {
$costLog = [
'module' => 'goods',
'action' => $request->getMethod(),
'target_type' => 'goods_sku',
'target_id' => $sku['id'],
'user_id' => $request->user()->id
];
// 成本
$goodsSku = GoodsSku::query()->where('id', $sku['id'])->first(['id', 'cost', 'stock', 'num']);
$costLog['target_field'] = 'cost';
$costLog['before_update'] = $goodsSku->cost;
$goodsSku->reference_price = $sku['cost'] * 1.5;
$goodsSku->cost = $sku['cost'];
$goodsSku->sale_stock = $sku['sale_stock'];
$goodsSku->save();
$costLog['after_update'] = $goodsSku->cost;
$logs[] = $costLog;
}
$log = new LogModel();
$log->batchInsert($logs);
DB::commit();
// 批量更新
event(new BatchStockUpdateEvent(array_column($request->skus, 'id')));
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
'httpCode' => 400,
'errorCode' => 400500,
'errorMessage' => $exception->getMessage(),
];
}
return response($this->res, $this->res['httpCode']);
}
/**
* 上新
*
@ -302,78 +350,8 @@ class GoodsSkusController extends Controller
*/
private function inventory($request)
{
DB::beginTransaction();
try {
$logs = [];
$requestSkus = ArrayUtils::index($request->skus, 'id');
$skus = GoodsSku::query()
->whereIn('id', array_keys($requestSkus))
->with(['goods:id,goods_code'])
->get(['id', 'goods_id', 'sku_code'])
->toArray();
$today = DateTimeUtils::getToday();
$nextDay = DateTimeUtils::getNextDay();
$dateTime = date('Y-m-d H:i:s');
foreach ($skus as $sku) {
if (!isset($requestSkus[$sku['id']])) {
continue;
}
// 更新今天
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', $today)->first();
// 日志记录
$inventoryLog = [
'module' => 'goods',
'action' => $request->getMethod(),
'target_type' => 'goods_sku',
'target_id' => $sku['id'],
'user_id' => $request->user()->id,
'target_field' => 'inventory',
'before_update' => $record->inventory,
'after_update' => $requestSkus[$sku['id']]['inventory']
];
$externalSkuId = $sku['goods']['goods_code'] . '_' . $sku['sku_code'];
// 自上一次盘点过后有订单发生的数量(包含退单)
$lastInventoryTime = $record->inventory_time;
$addOrderGoodsNum = BusinessOrderItem::query()
->where('external_sku_id', $externalSkuId)
->when($lastInventoryTime, function ($query) use ($lastInventoryTime) {
$query->where('updated_at', '>', $lastInventoryTime);
})
->sum('goods_number');
$reduceOrderGoodsNum = BusinessOrderItem::query()
->where('external_sku_id', $externalSkuId)
->when($lastInventoryTime, function ($query) use ($lastInventoryTime) {
$query->where('updated_at', '>', $lastInventoryTime);
})
->sum('already_cancel_number');
$orderGoodsNum = $addOrderGoodsNum - $reduceOrderGoodsNum;
$record->inventory = $requestSkus[$sku['id']]['inventory'];
$record->inventory_time = $dateTime;
$record->order_goods_num += $orderGoodsNum;
$record->save();
$inventoryLog['message'] = '盘点时订单商品数量: ' . $orderGoodsNum;
$logs[] = $inventoryLog;
// 更新明天
DailyStockRecord::updateOrCreate(
['sku_id' => $sku['id'], 'day' => $nextDay],
[
'inventory' => $record->inventory,
'inventory_time' => $dateTime,
]
);
}
$log = new LogModel();
$log->batchInsert($logs);
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
$this->res = [
'httpCode' => 400,
'errorCode' => 400500,
'errorMessage' => $exception->getMessage(),
];
}
$goodSkuService = new GoodSkuService();
$goodSkuService->inventory($request->skus);
return response($this->res, $this->res['httpCode']);
}

View File

@ -7,16 +7,20 @@ use App\Events\StockUpdateEvent;
use App\Exports\GoodsSkusExport;
use App\Exports\WeekDataExport;
use App\Http\Controllers\Controller;
use App\Http\Enum\ExcelKeyEnum;
use App\Http\Requests\GoodsRequest;
use App\Http\Requests\GoodsSkuRequest;
use App\Imports\InventoryImport;
use App\Imports\LossImport;
use App\Imports\NewSetImport;
use App\Imports\PurchaseImport;
use App\Models\BusinessOrderItem;
use App\Models\DailySalesReport;
use App\Models\DeveloperConfig;
use App\Models\Goods;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Models\LossRecords;
use App\Models\PurchaseRecords;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
@ -131,15 +135,18 @@ class WareHouseSkusController extends Controller
return GoodsSkuResource::collection($goodsSkus);
}
public function PurchaseBatchStore(Request $request)
/**
* 采购单后台批量存储
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|void
*/
public function purchaseBatchStore(Request $request)
{
$validator = Validator::make($request->all(), [
'purchaseOrders' => 'required|array',
'purchaseOrders.*.sku_id' => 'required|integer',
'purchaseOrders.*.external_sku_id' => 'required|string',
'purchaseOrders.*.num' => 'required|integer',
'purchaseOrders.*.cost' => 'required|string',
]);
'purchaseOrders.*.num' => 'required|integer']);
//参数校验
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
@ -152,8 +159,9 @@ class WareHouseSkusController extends Controller
$content .= "以上sku编码数据库中不存在";
return response($content, $this->res['httpCode']);
}
$goodsSkuMap = $goodsSku->pluck('external_sku_id',null)->toArray();
//执行库存操作
$goodsSkuMap = $goodsSku->pluck(null, 'external_sku_id')->toArray();
$updateIds = [];
//开始保存数据
foreach ($purchaseOrders as $v) {
$goodsSkuItem = $goodsSkuMap[$v['external_sku_id']];
//保存記錄
@ -171,100 +179,120 @@ class WareHouseSkusController extends Controller
GoodsSku::query()->where('external_sku_id', $v['external_sku_id'])->update([
'stock' => $goodsSkuItem['stock'] + $v['num'],
'sale_stock' => $goodsSkuItem['sale_stock'] + $v['num'],
'cost' => $v['cost'],
'cost' => number_format(($goodsSkuItem['stock']*$goodsSkuItem['cost']+$v['cost']*$v['num'])
/($goodsSkuItem['stock'] + $v['num']),2),
'status' => 1,
]);
event(new StockUpdateEvent($goodsSkuItem));
$updateIds[] = $goodsSkuItem['id'];
}
//如果是組合商品後續會處理组合商品库存的拆分
event(new BatchStockUpdateEvent($updateIds));
return response($this->res, $this->res['httpCode']);
}
public function updateField($id, Request $request)
/**
* 报损单后台批量存储
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|void
*/
public function purchaseImport(Request $request)
{
$rules = [
'updateField' => [
'required',
Rule::in(['reference_price', 'reserve', 'loss_num', 'status', 'goal_rate'])
],
'reference_price' => [
'sometimes',
'numeric',
'gt:0'
],
'reserve' => [
'sometimes',
'integer',
],
'loss_num' => [
'sometimes',
'integer',
],
'reason' => [
'sometimes',
'required',
'string'
],
'status' => [
'sometimes',
'required',
'integer',
Rule::in([0, 1, 2])
],
'goal_rate' => [
'sometimes',
'numeric',
],
if (!$request->hasFile(ExcelKeyEnum::PURCHASE_KEY)) {
$this->res = [
'httpCode' => 404,
'errorCode' => 404404,
'errorMessage' => 'not found purchase file',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
goto end;
}
$updateField = \request('updateField');
$sku = GoodsSku::query()->find($id);
if ('loss_num' === $updateField) {
$record = DailyStockRecord::query()
->where('sku_id', $id)
->where('day', DateTimeUtils::getToday())
->first(['id', 'loss_num']);
$this->log->message = $request->get('reason');
$this->setBeforeUpdateForLog($record->loss_num);
$record->loss_num += $request->loss_num;
$record->save();
$this->setAfterUpdateForLog($record->loss_num);
$sku->stock -= $request->loss_num;
$sku->save();
} else {
$this->setBeforeUpdateForLog($sku->$updateField);
if ('reserve' === $updateField) {
$changeNum = $sku->reserve - $request->reserve;
if (0 > $changeNum + $sku->stock) {
$this->setValidatorFailResponse('预留量超过库存数量');
goto end;
try {
$import = new PurchaseImport();
$path = $request->file(ExcelKeyEnum::PURCHASE_KEY);
Excel::import($import, $path);
$this->addLog(0, 'import', ExcelKeyEnum::PURCHASE_KEY);
} catch (ValidationException $exception) {
$this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());
}
$sku->stock += $changeNum;
}
$sku->$updateField = $request->$updateField;
$sku->save();
$this->setAfterUpdateForLog($sku->$updateField);
}
if (in_array($updateField, ['reserve', 'loss_num'])) {
event(new StockUpdateEvent($sku));
}
// 更新目标去化率
if ('goal_rate' === $updateField) {
DailySalesReport::query()
->where('date', date('Y-m-d'))
->where('goods_sku_id', $sku->id)
->update([
'goal_rate' => $request->$updateField
]);
}
$this->addLog($id, $updateField);
end:
return response($this->res, $this->res['httpCode']);
}
public function lossBatchStore(Request $request){
$validator = Validator::make($request->all(), [
'lossOrders' => 'required|array',
'lossOrders.*.external_sku_id' => 'required|string',
'lossOrders.*.num' => 'required|integer',
'lossOrders.*.reason' => 'sometimes|string',
'lossOrders.*.buyer_name' => 'sometimes|string',//采购商
]);
//参数校验
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$lossOrders = $request->input('lossOrders') ?? [];
$externalSkuIds = collect($lossOrders)->pluck("external_sku_id")->toArray();
$goodsSku = GoodsSku::query()->whereIn('external_sku_id', $externalSkuIds)->get();
if ($goodsSku->pluck("external_sku_id")->diff($externalSkuIds)->isNotEmpty()) {
$content = implode(',', $goodsSku->pluck("external_sku_id")->diff($externalSkuIds)->toArray());
$content .= "以上sku编码数据库中不存在";
return response($content, $this->res['httpCode']);
}
$goodsSkuMap = $goodsSku->pluck(null,'external_sku_id')->toArray();
$updateIds = [];
//开始保存数据
foreach ($lossOrders as $v) {
$goodsSkuItem = $goodsSkuMap[$v['external_sku_id']];
//保存記錄
$lossRecords = new LossRecords();
$lossRecords->sku_id = $goodsSkuItem['id'] ?? 0;
$lossRecords->external_sku_id = $v['external_sku_id'];
$lossRecords->num = $v['num'];
$lossRecords->cost = $v['cost'];
$lossRecords->buyer_name = $v['buyer_name'] ?? '';
$lossRecords->reason = $v['reason'] ?? '';
$lossRecords->save();
//更新库存
GoodsSku::query()->where('external_sku_id', $v['external_sku_id'])->update([
'stock' => $goodsSkuItem['stock'] - $v['num'],
'sale_stock' => $goodsSkuItem['sale_stock'] - $v['num'],
'cost' => number_format(($goodsSkuItem['stock']*$goodsSkuItem['cost']-$v['cost']*$v['num'])
/($goodsSkuItem['stock'] - $v['num']),2),
]);
$updateIds[] = $goodsSkuItem['id'];
}
//如果是組合商品後續會處理组合商品库存的拆分
event(new BatchStockUpdateEvent($updateIds));
return response($this->res, $this->res['httpCode']);
}
/**
* 报损单单后台批量导入
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|void
*/
public function lossImport(Request $request)
{
if (!$request->hasFile(ExcelKeyEnum::LOSS_KEY)) {
$this->res = [
'httpCode' => 404,
'errorCode' => 404404,
'errorMessage' => 'not found loss file',
];
}
try {
$import = new LossImport();
$path = $request->file(ExcelKeyEnum::LOSS_KEY);
Excel::import($import, $path);
$this->addLog(0, 'import', ExcelKeyEnum::LOSS_KEY);
} catch (ValidationException $exception) {
$this->setValidatorFailResponse($exception->validator->getMessageBag()->getMessages());
}
return response($this->res, $this->res['httpCode']);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Http\Enum;
class ExcelKeyEnum
{
const PURCHASE_KEY = "purchaseFile";
const LOSS_KEY = "lossFile";
}

View File

@ -7,6 +7,7 @@ use App\Jobs\SyncCostToMiaoXuan;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\TodayPrice;
use App\Services\GoodSku\GoodSkuService;
use App\Utils\DateTimeUtils;
use Exception;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
@ -20,85 +21,21 @@ class InventoryImport implements ToArray, SkipsEmptyRows
*/
public function array(array $collection)
{
$header = $collection[0];
unset($collection[0]);
$externalSkuId = [];
$requestSkus = [];
foreach ($collection as &$row) {
$row = array_map(static function ($v) {
return trim($v);
}, $row);
$externalSkuId[] = $row[0];
}
unset($row);
$updateIds = $todayPrice = [];
$day = DateTimeUtils::getToday();
$dateTime = date('Y-m-d H:i:s');
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuId)
->get(['id', 'status', 'external_sku_id'])
->toArray();
$hasGoodsSkus = ArrayUtils::index($hasGoodsSkus, 'external_sku_id');
foreach ($collection as $row) {
if (!isset($hasGoodsSkus[$row[0]])) {
continue;
}
$goodsSku = $hasGoodsSkus[$row[0]];
if ('下架' === $goodsSku['status']) {
GoodsSku::query()->where('id', $goodsSku['id'])->update([
'stock' => $row[2] + $row[3],
'cost' => $row[4],
'status' => 1,
]);
} else {
GoodsSku::query()->where('id', $goodsSku['id'])->update([
'stock' => $row[2] + $row[3],
'cost' => $row[4],
]);
}
SyncCostToMiaoXuan::dispatch($row[0], $row[4]);
$updateIds[] = $goodsSku['id'];
DailyStockRecord::query()->where('sku_id', $goodsSku['id'])->where('day', $day)->update([
'arrived_today_num' => $row[3],
'inventory' => $row[2],
'inventory_time' => $dateTime
]);
$shopPrice = [];
foreach ($row as $i => $v) {
if ($i > 4) {
$shopPrice[$header[$i]] = $v;
}
}
$todayPrice[] = [
'day' => $day,
'external_sku_id' => $goodsSku['external_sku_id'],
'shop_price' => json_encode($shopPrice, 256)
$requestSkus[] = [
"external_sku_id" => $row[0],
"inventory" => $row[2],
];
}
if ($todayPrice) {
TodayPrice::query()->delete();
$model = new TodayPrice();
$model->batchInsert($todayPrice);
}
sleep(2);
$onSkuIds = GoodsSku::query()
->where('is_combination', 0)
->where('status', '>', 0)
->pluck('id')
->toArray();
$downSkuIds = array_diff($onSkuIds, $updateIds);
if ($downSkuIds) {
$goodsSkus = GoodsSku::query()->whereIn('id', $downSkuIds)
->get(['id', 'yesterday_num', 'stock'])
->toArray();
foreach ($goodsSkus as $goodsSku) {
GoodsSku::query()->where('id', $goodsSku['id'])->update([
'yesterday_num' => $goodsSku['yesterday_num'] - $goodsSku['stock'],
'stock' => 0,
]);
}
}
sleep(2);
// 批量更新
event(new BatchStockUpdateEvent($onSkuIds));
unset($row);
//新版盘点excel字段 编码 商品名称 盘点数
$goodSkuService = new GoodSkuService();
$goodSkuService->inventory($requestSkus);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace App\Imports;
use App\Events\BatchStockUpdateEvent;
use App\Jobs\SyncCostToMiaoXuan;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\LossRecords;
use App\Models\PurchaseRecords;
use App\Utils\DateTimeUtils;
use Exception;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToArray;
use App\Utils\ArrayUtils;
class LossImport implements ToArray, SkipsEmptyRows
{
/**
* @throws Exception
*/
public function array(array $collection)
{
unset($collection[0]);
$externalSkuIds = [];
foreach ($collection as &$row) {
$row = array_map(static function ($v) {
return trim($v);
}, $row);
$externalSkuIds[] = $row[0];
}
unset($row);
$updateIds = [];
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'status', 'external_sku_id', 'stock'])
->toArray();
$hasGoodsSkus = ArrayUtils::index($hasGoodsSkus, 'external_sku_id');
//excel字段排序 編碼 商品名稱 报损數量 成本价 采购人名称 报损原因
foreach ($collection as $row) {
if (!isset($hasGoodsSkus[$row[0]])) {
continue;
}
//执行库存操作
$goodsSkuItem = $hasGoodsSkus[$row[0]];
//保存記錄
$lossRecords = new LossRecords();
$lossRecords->sku_id = $goodsSkuItem['id'] ?? 0;
$lossRecords->external_sku_id = $row[0];
$lossRecords->num = $row[2];
$lossRecords->cost = $row[3];
$lossRecords->buyer_name = $row[4] ?? '';
$lossRecords->reason = $row[5] ?? '';
$lossRecords->save();
//更新库存
GoodsSku::query()->where('external_sku_id', $row[0])->update([
'stock' => $goodsSkuItem['stock'] - $row[2],
'sale_stock' => $goodsSkuItem['sale_stock'] - $row[2],
'cost' => number_format(($goodsSkuItem['stock'] * $goodsSkuItem['cost'] - $row[3] * $row[2])
/ ($goodsSkuItem['stock'] - $row[2]), 2),
'status' => 1,
]);
$updateIds[] = $hasGoodsSkus['id'];
}
Log::info("报损导入内容:", $collection);
// 批量更新
event(new BatchStockUpdateEvent($updateIds));
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Imports;
use App\Events\BatchStockUpdateEvent;
use App\Jobs\SyncCostToMiaoXuan;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\PurchaseRecords;
use App\Utils\DateTimeUtils;
use Exception;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\ToArray;
use App\Utils\ArrayUtils;
class PurchaseImport implements ToArray, SkipsEmptyRows
{
/**
* @throws Exception
*/
public function array(array $collection)
{
unset($collection[0]);
$externalSkuIds = [];
foreach ($collection as &$row) {
$row = array_map(static function ($v) {
return trim($v);
}, $row);
$externalSkuIds[] = $row[0];
}
unset($row);
$updateIds = [];
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'status', 'external_sku_id', 'stock'])
->toArray();
$hasGoodsSkus = ArrayUtils::index($hasGoodsSkus, 'external_sku_id');
//excel字段排序 編碼 商品名稱 导购數量 成本价 采购人名称 供应商名称
foreach ($collection as $row) {
if (!isset($hasGoodsSkus[$row[0]])) {
continue;
}
//执行库存操作
$goodsSkuItem = $hasGoodsSkus[$row[0]];
//保存記錄
$purchaseRecords = new PurchaseRecords();
$purchaseRecords->sku_id = $goodsSkuItem['id'] ?? 0;
$purchaseRecords->external_sku_id = $row[0];
$purchaseRecords->num = $row[2];
$purchaseRecords->cost = $row[3];
$purchaseRecords->buyer_name = $row[4] ?? '';
$purchaseRecords->supplier_name = $row[5] ?? '';
$purchaseRecords->save();
//更新库存
GoodsSku::query()->where('external_sku_id', $row[0])->update([
'stock' => $goodsSkuItem['stock'] + $row[2],
'sale_stock' => $goodsSkuItem['sale_stock'] + $row[2],
'cost' => number_format(($goodsSkuItem['stock']*$goodsSkuItem['cost']+$row[3]*$row[2])
/($goodsSkuItem['stock'] + $row[2]),2),
'status' => 1,
]);
$updateIds[] = $hasGoodsSkus['id'];
}
Log::info("采购导入内容:",$collection);
// 批量更新
event(new BatchStockUpdateEvent($updateIds));
}
}

View File

@ -9,6 +9,7 @@ use App\Utils\DateTimeUtils;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Events\BatchStockUpdateEvent;
use Illuminate\Support\Facades\Log;
class CombinationGoodsStockUpdateListener implements ShouldQueue
{
@ -62,9 +63,12 @@ class CombinationGoodsStockUpdateListener implements ShouldQueue
foreach ($combinationGoods as $item) {
$goodsSku = GoodsSku::query()->find($item['item_id']);
$stock = $goodsSku->stock - $item['item_num'];
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock);
//新增逻辑 在线库存同步扣减
$saleStock = $goodsSku->sale_stock - $item['item_num'];
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock, $saleStock);
$goodsSku->status = $status;
$goodsSku->stock = $stock;
$goodsSku->sale_stock = $saleStock;
$goodsSku->save();
$updateIds[] = $goodsSku->id;
}
@ -76,18 +80,24 @@ class CombinationGoodsStockUpdateListener implements ShouldQueue
->pluck('goods_sku_id');
foreach ($goodsSkuIds as $goodsSkuId) {
$combinationGoods = CombinationGood::query()
->with('goodsSkuItem:id,stock')
->with('goodsSkuItem:id,stock,sale_stock')
->where('goods_sku_id', $goodsSkuId)
->get();
$stock = [];
$saleStock = [];
foreach ($combinationGoods as $goods) {
$stock[] = (int)($goods['goodsSkuItem']['stock'] / $goods['item_num']);
$saleStock[] = (int)($goods['goodsSkuItem']['sale_stock'] / $goods['item_num']);
}
//库存和在线可售库存都是通过子商品维护的
$stock = min($stock);
$saleStock = min($saleStock);
$goodsSku = GoodsSku::query()->find($goodsSkuId);
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock);
//新增在线可售逻辑判断 前置已经完成逻辑扣减或者增加
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock, $saleStock);
$goodsSku->status = $status;
$goodsSku->stock = $stock;
$goodsSku->sale_stock = $saleStock;
$goodsSku->save();
$updateIds[] = $goodsSkuId;
}
@ -99,21 +109,14 @@ class CombinationGoodsStockUpdateListener implements ShouldQueue
}
}
private function checkStatusAndStock($goodsSku, $stock)
private function checkStatusAndStock($goodsSku, $stock, $saleStock)
{
if (0 >= $stock) {
//下线库存判断以在线可售库存为准
if (0 >= $saleStock) {
$status = GoodsSku::$STATUS_DOWN;
} else {
$status = GoodsSku::$STATUS_ON_SALE;
}
$arrivedTodayNum = DailyStockRecord::query()
->where('day', DateTimeUtils::getToday())
->where('sku_id', $goodsSku->id)
->value('arrived_today_num');
if (20 < $arrivedTodayNum + $goodsSku->yesterday_num && 4 > $stock) {
$status = GoodsSku::$STATUS_DOWN;
$stock = 0;
}
return [$status, $stock];
}

View File

@ -60,7 +60,7 @@ class UpdateBusinessGoodsStock implements ShouldQueue
}
foreach ($shops as $shop) {
$num = $event->goodsSku->stock;
$num = $event->goodsSku->sale_stock;//同步三方和秒选虚拟库存
$businessGoodsSkus = BusinessGoodsSku::query()
->where('shop_id', $shop->id)
->where('is_sync', 1)

View File

@ -0,0 +1,57 @@
<?php
namespace App\Services\GoodSku;
use App\Events\BatchStockUpdateEvent;
use App\Events\CreateLogisticEvent;
use App\Models\BusinessOrderItem;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\Log as LogModel;
use App\Models\ShopShip;
use App\Models\Waybill;
use App\Services\Business\KuaiTuanTuan\FaceSheet;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Illuminate\Support\Facades\DB;
class GoodSkuService
{
public function inventory(array $requestSkus)
{
$requestSkusMap = collect($requestSkus)->pluck(null, 'external_sku_id')->toArray();
$externalSkuIds = collect($requestSkus)->pluck('external_sku_id')->toArray();
$skus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'external_sku_id'])
->toArray();
$today = DateTimeUtils::getToday();
$dateTime = date('Y-m-d H:i:s');
$updateIds = [];
foreach ($skus as $sku) {
if (!in_array($sku['external_sku_id'], $externalSkuIds)) {
continue;
}
// 更新
$record = DailyStockRecord::query()->where('sku_id', $sku['id'])->where('day', $today)->firstOrCreate([
'sku_id' => $sku['id'],
'day' => $today,
]);
$record->inventory = $requestSkusMap[$sku['external_sku_id']]['inventory'];
$record->inventory_time = $dateTime;
$record->save();
//查询sku当前未发货的数量 目前数据看着有问题暂不操作
//库存修改
GoodsSku::query()->where('id', $sku['id'])->lockForUpdate()->update([
'stock' => $requestSkusMap[$sku['external_sku_id']]['inventory']
]);
$updateIds[] = $sku['id'];
}
// 批量更新
event(new BatchStockUpdateEvent($updateIds));
}
}

View File

@ -22,7 +22,7 @@ class CreatePurchaseRecordsTable extends Migration
$table->string('buyer_name')->nullable()->comment('采购人');
$table->string('status')->default(0)->comment('盘点完近似状态 0未完成1已售卖完成');
$table->string('supplier_name')->nullable()->comment('供应商名称');
$table->unsignedDecimal('supplier_id')->nullable()->comment('供应商id');
$table->Integer('supplier_id')->nullable()->comment('供应商id');
// 索引
$table->index('sku_id');
$table->index('external_sku_id');

View File

@ -522,7 +522,38 @@ return [
],
'website_message.update' => [
'id' => 1912,
'name' => '站內信',
'name' => '更新',
'parent_id' => 191
],
'WARE_HOUSE' => [
'id' => 192,
'name' => '仓库管理',
'parent_id' => 19,
'show' => 1,
],
'goods.ware_house.index' => [
'id' => 1921,
'name' => '仓库管理首页',
'parent_id' => 192
],
'goods.ware_house.purchase_batch_store' => [
'id' => 1922,
'name' => '导购单批量保存',
'parent_id' => 192
],
'goods.ware_house.loss_batch_store' => [
'id' => 1923,
'name' => '报损单批量保存',
'parent_id' => 192
],
'goods.ware_house.purchase_import' => [
'id' => 1924,
'name' => '导购单批量导入',
'parent_id' => 192
],
'goods.ware_house.loss_import' => [
'id' => 1925,
'name' => '报损单批量导入',
'parent_id' => 192
],
];

View File

@ -12,6 +12,7 @@ use App\Http\Controllers\Group\GroupsController;
use App\Http\Controllers\Business\BusinessOrderController;
use App\Http\Controllers\Goods\GoodsSkuLocationController;
use App\Http\Controllers\Goods\GoodsCombinationController;
use App\Http\Controllers\Goods\WareHouseSkusController;
/*
|--------------------------------------------------------------------------
@ -72,9 +73,15 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::post('shop/ship/senders', [ShipController::class, 'saveSenders'])->name('shop_ship.senders.save');
// 数据中心
Route::get('data_center/sales_report', [DataCenterController::class, 'salesReport'])->name('sales_report.index');
//供应商
Route::resource('supplier', 'Supplier\SuppliersController', ['only' => ['index', 'update', 'store','destroy']]);
//站内信
Route::resource('website_message', 'Message\WebsiteMessageController', ['only' => ['index', 'update']]);
//仓库管理 采购和报损
Route::get('goods/ware_house/index', [WareHouseSkusController::class, 'index'])->name('goods.ware_house.index');
Route::post('goods/ware_house/purchase_batch_store', [WareHouseSkusController::class, 'purchaseBatchStore'])->name('goods.ware_house.purchase_batch_store');
Route::post('goods/ware_house/loss_batch_store', [WareHouseSkusController::class, 'lossBatchStore'])->name('goods.ware_house.loss_batch_store');
});
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');
@ -112,3 +119,9 @@ Route::post('today/price', [BusinessGoodsSkusController::class, 'todayPriceImpor
Route::post('upload', [UploadController::class, 'store'])->name('upload.file');
// 商品列表
Route::get('goodsSkusList', [GoodsSkusController::class, 'goodsSkusList'])->name('goods_sku.list_for_goods_sku');
// 采购导入
Route::post('goods/ware_house/purchase_import', [WareHouseSkusController::class, 'purchaseImport'])->name('goods.ware_house.purchase_import');
// 上新导入
Route::post('goods/ware_house/loss_import', [WareHouseSkusController::class, 'lossImport'])->name('goods.ware_house.loss_import');