采购单优化
This commit is contained in:
@@ -238,7 +238,8 @@ class PurchaseOrderController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* C4 商品行修改:采购成本同步该商品全部订货明细;实际称重按数量比例分摊(尾差修正守恒)
|
||||
* C4 商品行修改:品名/供应商/包规/单位/成本一键同步该商品全部订货明细;
|
||||
* 实际称重按数量比例分摊(尾差修正守恒)
|
||||
*/
|
||||
#[PutRoute(route: '/{id}/row/{productId}', authorize: 'update', where: ['id' => '[0-9]+', 'productId' => '[0-9]+'])]
|
||||
public function updateRow(int $id, int $productId, PurchaseRowUpdateRequest $request): JsonResponse
|
||||
@@ -248,13 +249,25 @@ class PurchaseOrderController extends BaseController
|
||||
throw new RepositoryException('采购单不存在');
|
||||
}
|
||||
$validated = $request->validated();
|
||||
$costPrice = isset($validated['cost_price']) ? (float) $validated['cost_price'] : null;
|
||||
|
||||
$attrs = [];
|
||||
foreach (['product_name', 'supplier_id', 'product_spec', 'unit', 'cost_price'] as $field) {
|
||||
if (isset($validated[$field])) {
|
||||
$attrs[$field] = $validated[$field];
|
||||
}
|
||||
}
|
||||
$weight = isset($validated['weight']) ? (float) $validated['weight'] : null;
|
||||
if ($costPrice === null && $weight === null) {
|
||||
throw new RepositoryException('采购成本与实际称重至少填写一项');
|
||||
if ($attrs === [] && $weight === null) {
|
||||
throw new RepositoryException('品名/供应商/包规/单位/成本/实际称重至少填写一项');
|
||||
}
|
||||
|
||||
$count = app(PurchaseEditService::class)->updateRow($purchase, $productId, $costPrice, $weight);
|
||||
$count = app(PurchaseEditService::class)->updateRow(
|
||||
$purchase,
|
||||
$productId,
|
||||
$attrs,
|
||||
$weight,
|
||||
(bool) ($validated['sync_product'] ?? false),
|
||||
);
|
||||
|
||||
return $this->success(['count' => $count], '已同步 ' . $count . ' 条订货明细');
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace App\Http\Requests\Purchase;
|
||||
use Modules\Common\Http\Requests\BaseFormRequest;
|
||||
|
||||
/**
|
||||
* 采购明细商品行修改 验证(C4;成本/称重至少填一项,同步到该商品全部订货明细)
|
||||
* 采购明细商品行修改 验证(C4;品名/供应商/包规/单位/成本/称重至少一项,
|
||||
* 提交后一键同步该商品在本采购单下的全部订货明细)
|
||||
*/
|
||||
class PurchaseRowUpdateRequest extends BaseFormRequest
|
||||
{
|
||||
@@ -14,14 +15,23 @@ class PurchaseRowUpdateRequest extends BaseFormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'product_name' => 'nullable|string|max:100',
|
||||
'supplier_id' => 'nullable|integer|exists:supplier,id',
|
||||
'product_spec' => 'nullable|string|max:100',
|
||||
'unit' => 'nullable|string|max:20',
|
||||
'cost_price' => 'nullable|numeric|min:0',
|
||||
'weight' => 'nullable|numeric|min:0',
|
||||
'sync_product' => 'nullable|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'product_name.max' => '品名不能超过 100 字',
|
||||
'supplier_id.exists' => '供应商不存在',
|
||||
'product_spec.max' => '包规不能超过 100 字',
|
||||
'unit.max' => '单位不能超过 20 字',
|
||||
'cost_price.numeric' => '采购成本必须为数字',
|
||||
'cost_price.min' => '采购成本不能小于 0',
|
||||
'weight.numeric' => '实际称重必须为数字',
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Exceptions\RepositoryException;
|
||||
use App\Models\ProductModel;
|
||||
use App\Models\PurchaseOrderModel;
|
||||
use App\Models\StoreOrderItemModel;
|
||||
use App\Models\StoreOrderModel;
|
||||
@@ -46,14 +47,16 @@ class PurchaseEditService
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品行修改:采购成本(写入该商品全部订货明细)/ 实际称重(按数量比例分摊,尾差修正守恒)
|
||||
* 商品行修改:品名/供应商/包规/单位/成本一键同步该商品全部订货明细;
|
||||
* 实际称重按数量比例分摊(尾差修正守恒);
|
||||
* syncProduct = true 时同步更新商品档案(product 表)
|
||||
*
|
||||
* @param float|null $costPrice 采购成本(每包规),NULL 不修改
|
||||
* @param array{product_name?: string, supplier_id?: int, product_spec?: string, unit?: string, cost_price?: float} $attrs 行属性(仅同步传入键)
|
||||
* @param float|null $weight 行实际称重合计,NULL 不修改
|
||||
*/
|
||||
public function updateRow(PurchaseOrderModel $purchase, int $productId, ?float $costPrice, ?float $weight): int
|
||||
public function updateRow(PurchaseOrderModel $purchase, int $productId, array $attrs, ?float $weight, bool $syncProduct = false): int
|
||||
{
|
||||
return DB::transaction(function () use ($purchase, $productId, $costPrice, $weight) {
|
||||
return DB::transaction(function () use ($purchase, $productId, $attrs, $weight, $syncProduct) {
|
||||
$items = StoreOrderItemModel::query()
|
||||
->where('purchase_id', $purchase->id)
|
||||
->where('product_id', $productId)
|
||||
@@ -63,11 +66,50 @@ class PurchaseEditService
|
||||
throw new RepositoryException('该采购单下无此商品的订货明细');
|
||||
}
|
||||
|
||||
if ($costPrice !== null) {
|
||||
$cost = bcadd((string) $costPrice, '0', 2);
|
||||
$sync = [];
|
||||
if (isset($attrs['product_name'])) {
|
||||
$sync['product_name'] = $attrs['product_name'];
|
||||
}
|
||||
if (isset($attrs['supplier_id'])) {
|
||||
$sync['supplier_id'] = (int) $attrs['supplier_id'];
|
||||
}
|
||||
if (isset($attrs['product_spec'])) {
|
||||
$sync['product_spec'] = $attrs['product_spec'];
|
||||
}
|
||||
if (isset($attrs['unit'])) {
|
||||
$sync['unit'] = $attrs['unit'];
|
||||
}
|
||||
if (isset($attrs['cost_price'])) {
|
||||
$sync['cost_price'] = bcadd((string) $attrs['cost_price'], '0', 2);
|
||||
}
|
||||
if ($sync !== []) {
|
||||
foreach ($items as $item) {
|
||||
$item->cost_price = $cost;
|
||||
$item->save();
|
||||
$item->fill($sync)->save();
|
||||
}
|
||||
|
||||
// 同步至商品档案(软删除商品不同步,直接报错回滚)
|
||||
if ($syncProduct) {
|
||||
$product = ProductModel::withTrashed()->find($productId);
|
||||
if ($product === null || $product->trashed()) {
|
||||
throw new RepositoryException('商品档案不存在或已删除,无法同步至商品');
|
||||
}
|
||||
$productAttrs = [];
|
||||
if (isset($sync['product_name'])) {
|
||||
$productAttrs['name'] = $sync['product_name'];
|
||||
}
|
||||
if (isset($sync['supplier_id'])) {
|
||||
$productAttrs['supplier_id'] = $sync['supplier_id'];
|
||||
}
|
||||
if (isset($sync['product_spec'])) {
|
||||
$productAttrs['spec'] = $sync['product_spec'];
|
||||
}
|
||||
if (isset($sync['unit'])) {
|
||||
$productAttrs['unit'] = $sync['unit'];
|
||||
}
|
||||
if (isset($sync['cost_price'])) {
|
||||
$productAttrs['cost_price'] = $sync['cost_price'];
|
||||
}
|
||||
$product->fill($productAttrs)->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user