基于order_stock表扣减stock_incoming表库存的MySQL逻辑问题排查
问题根因
你当前的代码仅完成了「订单与物料的关联绑定」操作,全程没有对stock_incoming库存表执行任何更新动作,自然无法实现库存扣减。除此之外,你的逻辑还缺少2个必要的校验环节:
- 扣减前未校验
stock_incoming表对应物料的剩余库存是否足够覆盖本次下单数量,会出现负库存异常 - 未开启事务保证「关联订单物料」和「扣减库存」两个操作的原子性,一旦其中一个步骤失败会出现数据不一致
调整方案
代码改造示例
你使用的是Laravel+Livewire技术栈,调整后的save方法逻辑如下:
public Order $order; public $selectedMat; public function save() { // 开启事务保证操作原子性 \DB::beginTransaction(); try { foreach ($this->selectedMat as $value) { // 按选中的stock_incoming id查询库存记录,高并发场景下可加lockForUpdate()行锁避免超卖 $stockIn = \App\Models\StockIncoming::where('id', $value['stock_in_id'])->lockForUpdate()->firstOrFail(); // 校验库存是否足够 if ($stockIn->remaining_qty < $value['qty']) { throw new \Exception("物料ID:{$value['id']} 库存不足,剩余{$stockIn->remaining_qty},需扣减{$value['qty']}"); } // 执行库存扣减 $stockIn->decrement('remaining_qty', $value['qty']); // 关联订单物料,建议冗余存储扣减的入库单ID方便后续对账 $this->order->materials()->attach([$value['id'] => [ 'qty' => $value['qty'], 'stock_in_id' => $value['stock_in_id'] ]]); } $this->order->refresh(); \DB::commit(); $this->emit('parent-refresh'); $this->emit('closeModal', 'matmodal'); } catch (\Exception $e) { \DB::rollBack(); // 可在此处增加前端错误提示逻辑 throw $e; } }
配套调整说明
- 确认前端传递的
selectedMat数组中已经包含选中的stock_in_id参数,对应stock_incoming表的主键ID - 建议给
order_stock表增加stock_in_id字段,用于关联本次扣减的入库记录,方便后续库存对账、退库等操作
内容的提问来源于stack exchange,提问作者HitoriDev
相关产品推荐
相关产品推荐

