优化采购单
This commit is contained in:
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Purchase;
|
||||
use App\Exceptions\RepositoryException;
|
||||
use App\Exports\PurchaseOrderExport;
|
||||
use App\Http\Requests\Purchase\PurchaseCellUpdateRequest;
|
||||
use App\Http\Requests\Purchase\PurchaseContainerUpdateRequest;
|
||||
use App\Http\Requests\Purchase\PurchaseRowUpdateRequest;
|
||||
use App\Models\ProductModel;
|
||||
use App\Models\PurchaseOrderModel;
|
||||
@@ -13,6 +14,7 @@ use App\Models\StoreOrderItemModel;
|
||||
use App\Models\StoreOrderModel;
|
||||
use App\Services\ItemImageResolver;
|
||||
use App\Services\PurchaseGenerateService;
|
||||
use App\Services\StoreOrderContainerService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -133,6 +135,45 @@ class PurchaseOrderController extends BaseController
|
||||
[$a['category_sort'], $a['product_sort'], $a['product_id']]
|
||||
<=> [$b['category_sort'], $b['product_sort'], $b['product_id']]);
|
||||
|
||||
// 周转框/托盘合并记录:按门店聚合全部订单(附底层订单明细,供采购单完成前修改)
|
||||
$storeOrders = StoreOrderModel::query()
|
||||
->where('purchase_id', $purchase->id)
|
||||
->whereNull('deleted_at')
|
||||
->orderBy('id')
|
||||
->get(['id', 'order_no', 'store_id', 'box_num', 'tray_num']);
|
||||
|
||||
$boxPrice = (float) site_config('services.box_amount', 0);
|
||||
$trayPrice = (float) site_config('services.tray_amount', 0);
|
||||
$storeSort = $stores->pluck('id')->flip();
|
||||
$containers = [];
|
||||
foreach ($storeOrders->groupBy('store_id') as $storeId => $orders) {
|
||||
$boxNum = (int) $orders->sum('box_num');
|
||||
$trayNum = (int) $orders->sum('tray_num');
|
||||
$containers[] = [
|
||||
'store_id' => (int) $storeId,
|
||||
'store_name' => $stores->firstWhere('id', (int) $storeId)['name'] ?? '门店#' . $storeId,
|
||||
'box_num' => $boxNum,
|
||||
'tray_num' => $trayNum,
|
||||
'box_price' => number_format($boxPrice, 2),
|
||||
'tray_price' => number_format($trayPrice, 2),
|
||||
'added_amount' => number_format($boxNum * $boxPrice + $trayNum * $trayPrice, 2),
|
||||
'order_count' => $orders->count(),
|
||||
'orders' => $orders->map(static fn (StoreOrderModel $order) => [
|
||||
'order_id' => $order->id,
|
||||
'order_no' => $order->order_no,
|
||||
'box_num' => (int) $order->box_num,
|
||||
'tray_num' => (int) $order->tray_num,
|
||||
])->values()->toArray(),
|
||||
'store_sort' => (int) ($storeSort[$storeId] ?? 9999),
|
||||
];
|
||||
}
|
||||
usort($containers, static fn (array $a, array $b): int =>
|
||||
[$a['store_sort'], $a['store_id']] <=> [$b['store_sort'], $b['store_id']]);
|
||||
$containers = array_map(static function (array $row): array {
|
||||
unset($row['store_sort']);
|
||||
return $row;
|
||||
}, $containers);
|
||||
|
||||
return $this->success([
|
||||
'purchase' => $purchase->toArray(),
|
||||
'stores' => $stores->toArray(),
|
||||
@@ -140,6 +181,7 @@ class PurchaseOrderController extends BaseController
|
||||
unset($row['category_sort'], $row['product_sort']);
|
||||
return $row;
|
||||
}, $rows),
|
||||
'containers' => $containers,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -395,6 +437,74 @@ class PurchaseOrderController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 周转框/托盘合并记录修改:按门店覆盖全部订单逐笔更新(仅采购单进行中可改)
|
||||
* @throws Throwable
|
||||
*/
|
||||
#[PutRoute(route: '/{id}/container/{storeId}', authorize: 'update', where: ['id' => '[0-9]+', 'storeId' => '[0-9]+'])]
|
||||
public function updateContainer(int $id, int $storeId, PurchaseContainerUpdateRequest $request): JsonResponse
|
||||
{
|
||||
$purchase = PurchaseOrderModel::find($id);
|
||||
if (empty($purchase)) {
|
||||
throw new RepositoryException('采购单不存在');
|
||||
}
|
||||
if ($purchase->status !== PurchaseOrderModel::STATUS_PENDING) {
|
||||
throw new RepositoryException('采购单已完成,不允许修改周转框/托盘');
|
||||
}
|
||||
|
||||
$submitted = $request->validated()['orders'];
|
||||
|
||||
return DB::transaction(function () use ($purchase, $storeId, $submitted) {
|
||||
$orders = StoreOrderModel::query()
|
||||
->where('purchase_id', $purchase->id)
|
||||
->where('store_id', $storeId)
|
||||
->whereNull('deleted_at')
|
||||
->lockForUpdate()
|
||||
->get();
|
||||
|
||||
if ($orders->isEmpty()) {
|
||||
throw new RepositoryException('该采购单下无此门店的订单');
|
||||
}
|
||||
|
||||
// 合并记录修改必须覆盖该门店全部订单,避免只改部分造成汇总偏差
|
||||
$actualIds = $orders->pluck('id')->map(static fn ($orderId) => (int) $orderId)->all();
|
||||
$submittedIds = array_map(static fn (array $row) => (int) $row['order_id'], $submitted);
|
||||
$missing = array_diff($actualIds, $submittedIds);
|
||||
if ($missing !== []) {
|
||||
throw new RepositoryException('提交不完整,缺少订单:' . implode('、', $missing));
|
||||
}
|
||||
if (array_diff($submittedIds, $actualIds) !== []) {
|
||||
throw new RepositoryException('包含不属于该采购单该门店的订单');
|
||||
}
|
||||
|
||||
foreach ($orders as $order) {
|
||||
if (! in_array($order->status, [
|
||||
StoreOrderModel::STATUS_SUMMARIZED,
|
||||
StoreOrderModel::STATUS_DELIVERING,
|
||||
StoreOrderModel::STATUS_DISTRIBUTION,
|
||||
], true)) {
|
||||
throw new RepositoryException(
|
||||
'订单 ' . $order->order_no . ' 当前状态为「'
|
||||
. (StoreOrderModel::STATUS_NAMES[$order->status] ?? $order->status)
|
||||
. '」,不允许修改周转框/托盘数量'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$ordersById = $orders->keyBy('id');
|
||||
$containerService = app(StoreOrderContainerService::class);
|
||||
foreach ($submitted as $row) {
|
||||
$containerService->update(
|
||||
$ordersById->get($row['order_id']),
|
||||
(int) $row['box_num'],
|
||||
(int) $row['tray_num'],
|
||||
);
|
||||
}
|
||||
|
||||
return $this->success();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品行修改:品名/供应商/包规/单位/成本
|
||||
* @throws Throwable
|
||||
|
||||
Reference in New Issue
Block a user