物品扫码领用与库存
This commit is contained in:
@@ -124,16 +124,28 @@ class InvItemService
|
||||
* @param int $itemId 物品ID
|
||||
* @param int $changeQty 变动数量:>0 入库,<0 出库
|
||||
* @param bool $allowNegative 是否允许库存变成负数,默认不允许
|
||||
*
|
||||
* @param array $options 额外选项(用于记录日志)
|
||||
* - biz_type: 业务类型
|
||||
* - biz_no: 单据号
|
||||
* - operator_id: 操作人ID
|
||||
* - operator_name: 操作人姓名
|
||||
* - remark: 备注
|
||||
* @return InvItem 最新的物品记录
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public function changeStock(int $itemId, int $changeQty, bool $allowNegative = false): InvItem
|
||||
public function changeStock(int $itemId, int $changeQty, bool $allowNegative = false, array $options = []): InvItem
|
||||
{
|
||||
if ($changeQty === 0) {
|
||||
throw new BusinessException('库存变动数量不能为 0');
|
||||
}
|
||||
|
||||
// 获取变动前的库存(用于日志)
|
||||
$itemBefore = InvItem::query()->find($itemId);
|
||||
if (!$itemBefore) {
|
||||
throw new BusinessException('物品不存在');
|
||||
}
|
||||
$beforeQty = $itemBefore->stock_qty;
|
||||
|
||||
$now = time();
|
||||
|
||||
// 构建查询
|
||||
@@ -154,39 +166,101 @@ class InvItemService
|
||||
// 更新不到行:
|
||||
// 1) 物品不存在
|
||||
// 2) 或者库存不足(不允许负数时)
|
||||
$exists = InvItem::query()->where('id', $itemId)->exists();
|
||||
if (! $exists) {
|
||||
throw new BusinessException('物品不存在');
|
||||
}
|
||||
throw new BusinessException('库存不足,无法完成库存变动');
|
||||
}
|
||||
|
||||
// 再查一次最新数据返回(在外层事务中也会保持一致)
|
||||
/** @var InvItem $item */
|
||||
$item = InvItem::query()->find($itemId);
|
||||
|
||||
// 记录库存变化日志
|
||||
$this->recordStockLog([
|
||||
'item_id' => $itemId,
|
||||
'item_name_snap' => $item->item_name,
|
||||
'change_qty' => $changeQty,
|
||||
'before_qty' => $beforeQty,
|
||||
'after_qty' => $item->stock_qty,
|
||||
'biz_type' => $options['biz_type'] ?? null,
|
||||
'biz_no' => $options['biz_no'] ?? null,
|
||||
'operator_id' => $options['operator_id'] ?? null,
|
||||
'operator_name' => $options['operator_name'] ?? null,
|
||||
'remark' => $options['remark'] ?? null,
|
||||
], $changeQty);
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库(减库存,默认不允许负数)
|
||||
*
|
||||
* @param int $itemId 物品ID
|
||||
* @param int $qty 出库数量
|
||||
* @param bool $allowNegative 是否允许负数
|
||||
* @param array $options 日志选项(同 changeStock)
|
||||
* @return InvItem
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public function stockOut(int $itemId, int $qty, bool $allowNegative = false): InvItem
|
||||
public function stockOut(int $itemId, int $qty, bool $allowNegative = false, array $options = []): InvItem
|
||||
{
|
||||
if ($qty <= 0) {
|
||||
throw new BusinessException('出库数量必须大于 0');
|
||||
}
|
||||
return $this->changeStock($itemId, -$qty, $allowNegative);
|
||||
// 确定变动类型:2-出库(领用)或 3-出库(损耗)
|
||||
$changeType = $options['change_type'] ?? \app\common\model\InvStockLog::CHANGE_TYPE_OUT_CLAIM;
|
||||
|
||||
return $this->changeStock($itemId, -$qty, $allowNegative, array_merge($options, [
|
||||
'change_type' => $changeType,
|
||||
'remark' => $options['remark'] ?? '领用出库',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库(加库存)
|
||||
*
|
||||
* @param int $itemId 物品ID
|
||||
* @param int $qty 入库数量
|
||||
* @param array $options 日志选项(同 changeStock)
|
||||
* @return InvItem
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public function stockIn(int $itemId, int $qty): InvItem
|
||||
public function stockIn(int $itemId, int $qty, array $options = []): InvItem
|
||||
{
|
||||
if ($qty <= 0) {
|
||||
throw new BusinessException('入库数量必须大于 0');
|
||||
}
|
||||
return $this->changeStock($itemId, $qty, true);
|
||||
// 确定变动类型:1-入库 或 4-入库(归还)
|
||||
$changeType = $options['change_type'] ?? \app\common\model\InvStockLog::CHANGE_TYPE_IN;
|
||||
|
||||
return $this->changeStock($itemId, $qty, true, array_merge($options, [
|
||||
'change_type' => $changeType,
|
||||
'remark' => $options['remark'] ?? '入库',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录库存变化日志
|
||||
*
|
||||
* @param array $logData
|
||||
* @param int $changeQty 变动数量
|
||||
* @return void
|
||||
*/
|
||||
private function recordStockLog(array $logData, int $changeQty): void
|
||||
{
|
||||
try {
|
||||
// 根据变动数量确定变动类型(如果未指定)
|
||||
if (!isset($logData['change_type'])) {
|
||||
if ($changeQty > 0) {
|
||||
$logData['change_type'] = \app\common\model\InvStockLog::CHANGE_TYPE_IN;
|
||||
} else {
|
||||
$logData['change_type'] = \app\common\model\InvStockLog::CHANGE_TYPE_OUT_CLAIM;
|
||||
}
|
||||
}
|
||||
|
||||
(new InvStockLogService())->record($logData);
|
||||
} catch (\Throwable $e) {
|
||||
// 日志记录失败不影响主业务,仅记录错误
|
||||
error_log('库存日志记录失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user