鲜花2.0-库存成本,周数据导出功能修改+增加库存变更记录

This commit is contained in:
杨建炊 2024-08-15 17:06:30 +08:00
parent 0e78cc2d43
commit bf67357601
12 changed files with 106 additions and 70 deletions

View File

@ -10,6 +10,7 @@ use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class BatchStockUpdateEvent
{

View File

@ -2,8 +2,10 @@
namespace App\Exports;
use App\Http\Enum\TargetTypeEnum;
use App\Models\DailyStockRecord;
use App\Models\Log;
use App\Models\PurchaseRecords;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Maatwebsite\Excel\Concerns\FromCollection;
@ -35,14 +37,12 @@ class GoodsSkusExport implements FromCollection, ShouldAutoSize
$headTitle = [
'商品编码',
'商品名称',
'商品种类',
'商品品牌',
'规格编码',
'商品品种',
'规格名称',
];
$map = [
'cost' => ['成本', '更新前成本', '更新后成本'],
'inventory' => ['库存', '盘点', '上新'],
'cost' => ['当前成本', '更新前成本', "更新后成本"],
'inventory' => ['当前库存', '盘点数', '采购总数'],
];
$headTitle = array_merge($headTitle, $map[$this->type]);
if ('cost' === $this->type) {
@ -70,21 +70,19 @@ class GoodsSkusExport implements FromCollection, ShouldAutoSize
}
$bodyData = [];
foreach ($data as $item) {
$arr[0] = $item['goods']['goods_code'];
$arr[1] = $item['goods']['title'];
$arr[2] = $item['goods']['type']['name'];
$arr[3] = $item['goods']['brand']['name'];
$arr[4] = $item['sku_code'];
$arr[5] = $item['title'];
$arr[0] = $item['external_sku_id'];
$arr[1] = $item['name'];
$arr[2] = !empty($item['goods']['type']['name']) ? $item['goods']['type']['name'] : '';
$arr[3] = $item['title'];
if ('cost' === $this->type) {
$arr[6] = (string)$item['cost'];
$arr[7] = (string)$update[$item['id']]['before_update'];
$arr[8] = (string)$update[$item['id']]['after_update'];
$arr[4] = (string)$item['cost'];
$arr[5] = (string)$update[$item['id']]['before_update'];
$arr[6] = (string)$update[$item['id']]['after_update'];
}
if ('inventory' === $this->type) {
$arr[6] = (string)$item['stock'];
$arr[7] = (string)$update[$item['id']]['inventory'];
$arr[8] = (string)$update[$item['id']]['arrived_today_num'];
$arr[4] = (string)$item['stock'];
$arr[5] = (string)$update[$item['id']]['inventory'];
$arr[6] = (string)$update[$item['id']]['arrived_today_num'];
}
$bodyData[] = $arr;
}
@ -97,18 +95,23 @@ class GoodsSkusExport implements FromCollection, ShouldAutoSize
$day = DateTimeUtils::getToday();
$logs = Log::query()
->select(['target_id', 'before_update', 'after_update'])
->where('target_type', 'goods_sku')
->where('target_field', 'cost')
->where('target_type', TargetTypeEnum::PURCHASE)
->where('target_field', 'stock')
->where('created_at', '>', $day)
->orderBy('id', 'asc')
->get();
$update = [];
foreach ($logs as $log) {
if ($log['before_update'] !== $log['after_update'] || (int)$log['after_update']) {
if (!isset($update[$log['target_id']])) {
$update[$log['target_id']]['before_update'] = $log['before_update'];
$beforeData = json_decode($log['before_update'], true);
if (!empty($beforeData['cost'])) {
$update[$log['target_id']]['before_update'] = $beforeData['cost'];
}
$update[$log['target_id']]['after_update'] = $log['after_update'];
}
$afterData = json_decode($log['after_update'], true);
if (!empty($afterData['cost']) && $afterData['cost'] != $beforeData['cost']) {
$update[$log['target_id']]['after_update'] = $afterData['cost'];
}
}

View File

@ -33,9 +33,8 @@ class WeekDataExport implements FromCollection, ShouldAutoSize
{
$headTitle = [
'商品名称',
'品类',
'规格',
'品牌',
'品种',
'规格名称',
'商品编码',
'成本',
'销售数量',
@ -51,8 +50,7 @@ class WeekDataExport implements FromCollection, ShouldAutoSize
->with([
'goods:id,title',
'goodsType:id,name',
'goodsSku:id,title',
'goodsBrand:id,name',
'goodsSku:id,title,name'
])
->where('date', '>=', $this->startDate)
->where('date', '<=', $this->endDate)
@ -66,10 +64,9 @@ class WeekDataExport implements FromCollection, ShouldAutoSize
$number = $item->total_goods_number - $item->total_cancel_number;
if (!isset($arr[$item->external_sku_id])) {
$arr[$item->external_sku_id] = [
'goodsTitle' => $item->goods->title,
'goodsTypeName' => $item->goodsType->name,
'goodsSkuTitle' => $item->goodsSku->title,
'goodsBrandName' => $item->goodsBrand->name,
'goodsTitle' => !empty($item->goodsSku) ? $item->goodsSku->name:'',
'goodsTypeName' => !empty($item->goodsType) ? $item->goodsType->name : "",
'goodsSkuTitle' => !empty($item->goodsSku) ? $item->goodsSku->title : "",
'external_sku_id' => $item->external_sku_id,
'cost' => [],
'number' => [],
@ -97,7 +94,6 @@ class WeekDataExport implements FromCollection, ShouldAutoSize
$item['goodsTitle'],
$item['goodsTypeName'],
$item['goodsSkuTitle'],
$item['goodsBrandName'],
$item['external_sku_id'],
$cost,
array_sum($item['number']),

View File

@ -193,11 +193,8 @@ class GoodsCombinationController extends Controller
public function goodsSkus(Request $request, $title)
{
$goodsIds = Goods::query()
->where('title', 'like', '%' . $title . '%')
->pluck('id');
$skus = GoodsSku::query()
->whereIn('goods_id', $goodsIds)
->where('title', 'like', '%' . $title . '%')
->where('is_combination', 0)
->with('goods:id,title')
->get(['id', 'title', 'goods_id']);

View File

@ -84,12 +84,10 @@ class DailyStockRecordController extends Controller
*/
public function inventoryBatchStore(Request $request)
{
$validator = Validator::make($request->all(), [
'inventoryOrders' => 'required|array',
'inventoryOrders.*.external_sku_id' => 'required|string',
'inventoryOrders.*.inventory' => 'required|integer',
]);
if ($validator->fails()) {
//校验失败返回异常

View File

@ -158,7 +158,7 @@ class LossRecordController extends Controller
return response($content, $this->res['httpCode']);
}
$goodsSkuMap = $goodsSku->pluck(null, 'external_sku_id')->toArray();
$updateIds = [];
$allUpdateIds = [];
$batchNumber = GeneratorUtils::generateBatchNumber();
$today = DateTimeUtils::getToday();
//开始保存数据
@ -178,10 +178,10 @@ class LossRecordController extends Controller
$lossRecords->save();
$updateIds = GoodSkuService::computeSkuStock($goodsSkuItem, ['num' => 0 - $v['num'], "cost" => $v['cost']]);
$allUpdateIds = array_merge($allUpdateIds, $updateIds);
}
event(new BatchStockUpdateEvent($updateIds));
event(new BatchStockUpdateEvent(collect($allUpdateIds)->unique()->toArray()));
return response($this->res, $this->res['httpCode']);
}

View File

@ -180,7 +180,7 @@ class PurchaseRecordController extends Controller
return response($content, $this->res['httpCode']);
}
$goodsSkuMap = $goodsSku->pluck(null, 'external_sku_id')->toArray();
$updateIds = [];
$allUpdateIds = [];
$expireDay = DeveloperConfigService::getDefaultExpireDay();
$today = DateTimeUtils::getToday();
$batchNumber = GeneratorUtils::generateBatchNumber();
@ -202,10 +202,11 @@ class PurchaseRecordController extends Controller
$purchaseRecords->save();
$updateIds = GoodSkuService::computeSkuStock($goodsSkuItem, $v, TargetTypeEnum::PURCHASE);
$allUpdateIds = array_merge($allUpdateIds, $updateIds);
}
//如果是組合商品会触发重算逻辑
event(new BatchStockUpdateEvent($updateIds));
event(new BatchStockUpdateEvent(collect($allUpdateIds)->unique()->toArray()));
return response($this->res, $this->res['httpCode']);
}

View File

@ -6,8 +6,10 @@ namespace App\Http\Enum;
class TargetTypeEnum
{
const PURCHASE = "purchase";
const PURCHASE = "sku_stock_purchase";
const LOSS = "loss";
const LOSS = "sku_stock_loss";
const INVENTORY = "sku_stock_inventory";
}

View File

@ -38,7 +38,7 @@ class LossImport implements ToArray, SkipsEmptyRows
$buyerNames[] = $row[4];
}
unset($row);
$updateIds = [];
$allUpdateIds = [];
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'status', 'external_sku_id', 'stock', "sale_stock", "cost", "is_combination"])
@ -71,11 +71,12 @@ class LossImport implements ToArray, SkipsEmptyRows
}
$lossRecords->save();
$updateIds += GoodSkuService::computeSkuStock($goodsSkuItem, ["num" => 0 - $row[2], 'cost' => $row[3]]);
$updateIds = GoodSkuService::computeSkuStock($goodsSkuItem, ["num" => 0 - $row[2], 'cost' => $row[3]]);
$allUpdateIds = array_merge($allUpdateIds, $updateIds);
}
Log::info("报损导入内容:", $collection);
// 批量更新
event(new BatchStockUpdateEvent(collect($updateIds)->unique()->toArray()));
event(new BatchStockUpdateEvent(collect($allUpdateIds)->unique()->toArray()));
}

View File

@ -42,7 +42,7 @@ class PurchaseImport implements ToArray, SkipsEmptyRows
$supplierNames[] = $row[5];
}
unset($row);
$updateIds = [];
$allUpdateIds = [];
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'status', 'external_sku_id', 'stock', "sale_stock", "cost", "is_combination"])
@ -80,11 +80,13 @@ class PurchaseImport implements ToArray, SkipsEmptyRows
$purchaseRecords->expire_time = Carbon::now()->addDays($expireDay)->toDateTimeString();
$purchaseRecords->save();
$updateIds += GoodSkuService::computeSkuStock($goodsSkuItem, ["num" => $row[2], 'cost' => $row[3]], TargetTypeEnum::PURCHASE);
$updateIds = GoodSkuService::computeSkuStock($goodsSkuItem, ["num" => $row[2], 'cost' => $row[3]], TargetTypeEnum::PURCHASE);
$allUpdateIds = array_merge($allUpdateIds, $updateIds);
}
Log::info("采购导入内容:", $collection);
Log::info("allUpdateIds:", $allUpdateIds);
// 批量更新
event(new BatchStockUpdateEvent(collect($updateIds)->unique()->toArray()));
event(new BatchStockUpdateEvent(collect($allUpdateIds)->unique()->toArray()));
}
}
}

View File

@ -103,6 +103,7 @@ class CombinationGoodsStockUpdateListener implements ShouldQueue
$updateIds[] = $goodsSkuId;
}
}
if ($updateIds) {
$updateIds = array_unique($updateIds);
// 批量更新

View File

@ -8,6 +8,7 @@ use App\Models\BusinessOrderItem;
use App\Models\CombinationGood;
use App\Models\DailyStockRecord;
use App\Models\GoodsSku;
use App\Models\Log as LogModel;
use App\Utils\DateTimeUtils;
use App\Utils\GeneratorUtils;
use Carbon\Carbon;
@ -52,7 +53,7 @@ class GoodSkuService
DB::beginTransaction();
try {
foreach ($skusWithCombinationGoods as $sku) {
// 更新
// 更新每日数据
DailyStockRecord::query()->updateOrCreate([
'sku_id' => $sku['id'],
'day' => $today,
@ -62,19 +63,26 @@ class GoodSkuService
"batch_number" => $batchNumber
]);
}
$costLogs = [];
//更新库存并记录数据
foreach ($inventoryKeyBySkuIdMap as $skuId => $realStock) {
//库存修改 盘点是直接覆盖
GoodsSku::query()->where('id', $skuId)->update([
'stock' => $realStock
]);
$skuData = GoodsSku::query()->where('id', $skuId)->first();
if(!empty($skuData)){
$costLogs[] = static::addStockLog($skuData, []
, TargetTypeEnum::INVENTORY, ['stock' => $realStock]);
$skuData->stock = $realStock;
$skuData->save();
$updateIds[] = $skuId;
}
}
$log = new LogModel();
$log->batchInsert($costLogs);
DB::commit();
} catch (\Exception $exception) {
DB::rollBack();
Log::error("库存盘点异常", ["error" => $exception->getMessage()]);
}
// 批量更新
@ -113,39 +121,65 @@ class GoodSkuService
}
public static function computeSkuStock(array $goodsSkuItem, array $v, $targetType = TargetTypeEnum::LOSS)
public static function computeSkuStock(array $goodsSkuItem, array $changeData, $targetType = TargetTypeEnum::LOSS)
{
$updateIds = [];
Log::info("库存更新前完整商品信息", $goodsSkuItem);
Log::info("库存更新前完整请求信息", $v);
Log::info("库存更新前完整请求信息", $changeData);
$updateParams = [];
//添加系统日志
$costLogs = [];
// 成本
if (empty($goodsSkuItem['is_combination'])) {
$updateParam = [
'stock' => $goodsSkuItem['stock'] + $v['num'],
'sale_stock' => $goodsSkuItem['sale_stock'] + $v['num'],
'stock' => $goodsSkuItem['stock'] + $changeData['num'],
'sale_stock' => $goodsSkuItem['sale_stock'] + $changeData['num'],
];
if ($targetType == TargetTypeEnum::PURCHASE) {
$updateParam['cost'] = $v['cost'];
$updateParam['cost'] = $changeData['cost'];
}
GoodsSku::query()->where('external_sku_id', "=", $goodsSkuItem['external_sku_id'])
->update($updateParam);
$updateIds[] = $goodsSkuItem['id'];
$updateParams[] = $updateParam;
$costLogs[] = static::addStockLog($goodsSkuItem, $changeData, $targetType, $updateParam);
} else {
$combinationGood = CombinationGood::query()->with('goodsSkuItem:id,stock,sale_stock')
->where('goods_sku_id', $goodsSkuItem['id'])->get();
foreach ($combinationGood as $item) {
$updateParam = [
'stock' => $item['goodsSkuItem']['stock'] + $v['num'] * $item['item_num'],
'sale_stock' => $item['goodsSkuItem']['sale_stock'] + $v['num'] * $item['item_num'],
'stock' => $item['goodsSkuItem']['stock'] + $changeData['num'] * $item['item_num'],
'sale_stock' => $item['goodsSkuItem']['sale_stock'] + $changeData['num'] * $item['item_num'],
];
GoodsSku::query()->where('id', $item['goodsSkuItem']['id'])->update($updateParam);
$updateIds[] = $item['goodsSkuItem']['id'];
$updateParams[] = $updateParam;
$costLogs[] = static::addStockLog($item['goodsSkuItem'], $changeData, $targetType, $updateParam);
}
}
$log = new LogModel();
$log->batchInsert($costLogs);
Log::info("本次请求更新参数", $updateParams);
return $updateIds;
}
public static function addStockLog($goodsSkuItem, $changeData, $targetType = TargetTypeEnum::LOSS, $updateParam)
{
$costLog = [
'module' => 'goodSkus',
'action' => "POST",
'target_type' => $targetType,
'target_id' => $goodsSkuItem['id'] ?? 0,
'user_id' => $changeData['user_id'] ?? 999,
"target_field" => "stock"
];
$costLog['before_update'] = json_encode($goodsSkuItem);
$costLog['after_update'] = json_encode($updateParam);
return $costLog;
}
}