where('purchase_id', $purchase->id) ->where('product_id', $productId) ->lockForUpdate() ->get(); if ($items->isEmpty()) { throw new RepositoryException('该采购单下无此商品的订货明细'); } $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->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(); } } $this->recalculatePurchaseTotals($purchase); return $items->count(); }); } /** * 重算采购金额汇总 */ public function recalculatePurchaseTotals(PurchaseOrderModel $purchase): void { $items = StoreOrderItemModel::query() ->where('purchase_id', $purchase->id) ->get(['quantity', 'cost_price']); $totalQuantity = 0; $estimate = '0'; foreach ($items as $item) { $totalQuantity += $item->quantity; $item_estimate = bcmul($item->cost_price, $item->quantity, 2); $estimate = bcadd($estimate, $item_estimate, 2); } $purchase->total_quantity = $totalQuantity; $purchase->estimate_amount = $estimate; $purchase->save(); } /** * 采购成本金额:称重>0 按 称重×单价,否则按 数量×单价 */ public static function costAmount(string $quantity, string $weight, string $unitCost): string { return (float) $weight > 0 ? bcmul($weight, $unitCost, 2) : bcmul($quantity, $unitCost, 2); } /** * 单价 = 成本 / 包规数值(spec 解析不出正数时按 1 处理,即单价=成本) */ public static function unitCost(string $costPrice, string $spec): string { if (preg_match('/\d+(?:\.\d+)?/', $spec, $matches) === 1 && (float) $matches[0] > 0) { return bcdiv($costPrice, $matches[0], 2); } return bcadd($costPrice, '0', 2); } }