erp/app/Http/Controllers/Goods/WareHouseSkusController.php

271 lines
9.9 KiB
PHP
Raw Normal View History

2024-07-25 17:54:14 +08:00
<?php
namespace App\Http\Controllers\Goods;
use App\Events\BatchStockUpdateEvent;
use App\Events\StockUpdateEvent;
use App\Exports\GoodsSkusExport;
use App\Exports\WeekDataExport;
use App\Http\Controllers\Controller;
use App\Http\Requests\GoodsRequest;
use App\Http\Requests\GoodsSkuRequest;
use App\Imports\InventoryImport;
use App\Imports\NewSetImport;
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\PurchaseRecords;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\GoodsSku;
use App\Http\Resources\GoodsSkuResource;
use App\Imports\GoodsSkusImport;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\DailyStockRecord;
use App\Models\Shop;
class WareHouseSkusController extends Controller
{
public function __construct(Request $request)
{
$this->log = new LogModel([
'module' => 'goods',
'action' => $request->getMethod(),
'target_type' => 'goods_sku',
]);
}
public function index(Request $request)
{
$fields = implode(',', [
'shop_id',
'external_sku_id',
'SUM(goods_number) - SUM(already_cancel_number) as number',
]);
$orderRestTime = DeveloperConfig::query()
->where('key', DeveloperConfig::$ORDER_RESET_TIME)
->value('value');
if (is_null($orderRestTime)) {
$orderRestTime = date('Y-m-d 07:00:00');
}
$businessOrderItems = BusinessOrderItem::query()
->select(DB::raw($fields))
->with([
'shop:id,name',
'goodsSku:id,external_sku_id'
])
->where('created_at', '>', $orderRestTime)
->where('external_sku_id', '<>', '')
->groupBy(['shop_id', 'external_sku_id'])
->orderByDesc('number')
->get()
->toArray();
$ids = $externals = [];
foreach ($businessOrderItems as $businessOrderItem) {
if (is_null($businessOrderItem['goods_sku'])) {
continue;
}
$id = $businessOrderItem['goods_sku']['id'];
if (isset($ids[$id])) {
$ids[$id] += (int)$businessOrderItem['number'];
} else {
$ids[$id] = (int)$businessOrderItem['number'];
}
$externals[$businessOrderItem['external_sku_id']][] = $businessOrderItem;
}
arsort($ids);
$builder = GoodsSku::query();
$this->preparQueryGoodsSkus($request, $builder);
$day = DateTimeUtils::getToday();
$goodsSkus = (clone $builder)->filter()
->where('is_combination', 0)
->orderByDesc('stock')
->pluck('stock', 'id')
->toArray();
$finalIds = [];
foreach ($ids as $id => $number) {
if (isset($goodsSkus[$id])) {
$finalIds[] = $id;
unset($goodsSkus[$id]);
}
}
$finalIds = array_merge($finalIds, array_keys($goodsSkus));
$idField = implode(',', $finalIds);
$goodsSkus = (clone $builder)->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->with(['daily' => function ($query) use ($day) {
$query->where('day', $day);
}])
->whereIn('id', $finalIds)
->orderByRaw("FIELD(id, {$idField})")
->paginate($request->get('per_page'));
$rolesName = $request->user()->getRoleNames()->toArray();
foreach ($goodsSkus as &$sku) {
$lastInventoryTime = $sku['daily']['inventory_time'] ?: date('Y-m-d 07:00:00');
if (isset($externals[$sku['external_sku_id']])) {
$sku['order_detail'] = $externals[$sku['external_sku_id']];
$sku['order_goods_num'] = array_sum(array_column($externals[$sku['external_sku_id']], 'number'));
} else {
$sku['order_detail'] = [];
$sku['order_goods_num'] = 0;
}
$sku['order_goods_num'] -= $sku['daily']['reissue_num'];
$sku['inventory_time'] = $lastInventoryTime;
if ('销售' === $rolesName[0]) {
$sku['cost'] = 0;
}
}
return GoodsSkuResource::collection($goodsSkus);
}
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',
]);
if ($validator->fails()) {
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
$purchaseOrders = $request->input('purchaseOrders') ?? [];
$externalSkuIds = collect($purchaseOrders)->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('external_sku_id',null)->toArray();
//执行库存操作
foreach ($purchaseOrders as $v) {
$goodsSkuItem = $goodsSkuMap[$v['external_sku_id']];
//保存記錄
$purchaseRecords = new PurchaseRecords();
$purchaseRecords->sku_id = $goodsSkuItem['id'] ?? 0;
$purchaseRecords->external_sku_id = $v['external_sku_id'];
$purchaseRecords->num = $v['num'];
$purchaseRecords->cost = $v['cost'];
$purchaseRecords->buyer_name = $v['buyer_name'] ?? '';
$purchaseRecords->supplier_name = $v['supplier_name'] ?? '';
$purchaseRecords->supplier_id = $v['supplier_id'] ?? 0;
$purchaseRecords->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' => $v['cost'],
'status' => 1,
]);
event(new StockUpdateEvent($goodsSkuItem));
}
}
public function updateField($id, 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',
],
];
$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;
}
$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']);
}
}