fix: support stock adjustment for items without stocktake draft

This commit is contained in:
DXC
2026-03-18 13:53:55 +08:00
parent e08012d9dd
commit 33969b8336
2 changed files with 59 additions and 31 deletions

View File

@ -364,10 +364,16 @@ def adjust_stock():
1. 根据 diff_qty 调整库存 (stock_quantity 和 available_quantity) 1. 根据 diff_qty 调整库存 (stock_quantity 和 available_quantity)
2. 生成流水账记录 (盘盈入库 / 盘亏出库) 2. 生成流水账记录 (盘盈入库 / 盘亏出库)
3. 标记草稿为 is_processed=True 3. 标记草稿为 is_processed=True
支持两种模式:
- 有草稿模式:通过 draft_id 或 stock_id+source_table 查找草稿
- 无草稿模式:直接传入 stock_id + diff_qty + source_table未扫码直接盘亏
""" """
data = request.json data = request.json
draft_id = data.get('draft_id') draft_id = data.get('draft_id')
stock_id = data.get('stock_id') # 备用参数:通过 stock_id 查找草稿 stock_id = data.get('stock_id')
diff_qty = data.get('diff_qty')
source_table = data.get('source_table')
operator_name = data.get('operator_name', 'System') operator_name = data.get('operator_name', 'System')
remark = data.get('remark', '') remark = data.get('remark', '')
@ -375,26 +381,34 @@ def adjust_stock():
return jsonify({"message": "draft_id 或 stock_id 不能同时为空"}), 400 return jsonify({"message": "draft_id 或 stock_id 不能同时为空"}), 400
try: try:
# 1. 获取草稿记录(优先用 draft_id否则用 stock_id # 1. 尝试获取草稿
draft = StocktakeDraft.query.get(draft_id) if draft_id else None draft = StocktakeDraft.query.get(draft_id) if draft_id else None
if not draft and stock_id: if not draft and stock_id and source_table:
# 尝试通过 stock_id 查找未处理的草稿 draft = StocktakeDraft.query.filter_by(
stock_id=stock_id,
source_table=source_table
).first()
elif not draft and stock_id:
draft = StocktakeDraft.query.filter_by(stock_id=stock_id).first() draft = StocktakeDraft.query.filter_by(stock_id=stock_id).first()
if not draft:
return jsonify({"message": f"平账失败找不到对应的盘点草稿记录draft_id={draft_id}, stock_id={stock_id}"}), 404
# 2. 获取库存记录 # 2. 核心逻辑分支
if not draft.stock_id or not draft.source_table: if draft:
return jsonify({"message": "草稿记录缺少库存关联信息"}), 400 # 有草稿模式
stock_id = draft.stock_id
source_table = draft.source_table
diff_qty = float(draft.diff_qty)
else:
# 无草稿模式(未扫码直接盘亏)
if diff_qty is None or source_table is None or not stock_id:
return jsonify({"message": "未扫码物资平账缺失必要参数(需提供 diff_qty 和 source_table"}), 400
diff_qty = float(diff_qty)
stock = get_stock_record(draft.source_table, draft.stock_id) # 3. 获取并校验真实的库存记录
stock = get_stock_record(source_table, stock_id)
if not stock: if not stock:
return jsonify({"message": "库存记录不存在"}), 404 return jsonify({"message": "平账失败:物理库存记录不存在"}), 404
diff_qty = float(draft.diff_qty) # 4. 计算调整
# 3. 计算调整
if diff_qty > 0: if diff_qty > 0:
# 盘盈:增加库存 # 盘盈:增加库存
new_stock_qty = float(stock.stock_quantity or 0) + diff_qty new_stock_qty = float(stock.stock_quantity or 0) + diff_qty
@ -415,19 +429,20 @@ def adjust_stock():
else: else:
return jsonify({"message": "差异为0无需调整"}), 400 return jsonify({"message": "差异为0无需调整"}), 400
# 4. 执行库存调整 # 5. 执行库存调整
stock.stock_quantity = new_stock_qty stock.stock_quantity = new_stock_qty
stock.available_quantity = new_avail_qty stock.available_quantity = new_avail_qty
# 5. 生成流水账记录 # 6. 生成流水账记录
# 导入流水账模型
from app.models.outbound import TransOutbound from app.models.outbound import TransOutbound
# 生成唯一单号
adj_no_suffix = draft.id if draft else f"MANUAL-{datetime.now().strftime('%Y%m%d%H%M%S')}"
trans_record = TransOutbound( trans_record = TransOutbound(
outbound_no=f"STKADJ-{datetime.now().strftime('%Y%m%d%H%M%S')}-{draft.id:04d}", outbound_no=f"STKADJ-{datetime.now().strftime('%Y%m%d%H%M%S')}-{adj_no_suffix}",
sku=stock.sku, sku=stock.sku,
source_table=draft.source_table, source_table=source_table,
stock_id=draft.stock_id, stock_id=stock_id,
barcode=getattr(stock, 'barcode', ''), barcode=getattr(stock, 'barcode', ''),
quantity=abs(diff_qty), quantity=abs(diff_qty),
unit_price=getattr(stock, 'pre_tax_unit_price', 0) or getattr(stock, 'manual_cost', 0) or 0, unit_price=getattr(stock, 'pre_tax_unit_price', 0) or getattr(stock, 'manual_cost', 0) or 0,
@ -439,8 +454,9 @@ def adjust_stock():
) )
db.session.add(trans_record) db.session.add(trans_record)
# 6. 删除草稿记录(平账后从工作台移除 # 7. 删除草稿记录(仅在有草稿时
db.session.delete(draft) if draft:
db.session.delete(draft)
db.session.commit() db.session.commit()
@ -450,7 +466,7 @@ def adjust_stock():
"diff_qty": diff_qty, "diff_qty": diff_qty,
"new_stock_qty": new_stock_qty, "new_stock_qty": new_stock_qty,
"new_avail_qty": new_avail_qty, "new_avail_qty": new_avail_qty,
"draft_id": draft_id "draft_id": draft_id if draft_id else (draft.id if draft else None)
}), 200 }), 200
except Exception as e: except Exception as e:

View File

@ -448,14 +448,16 @@ const api = {
params: {} params: {}
}), }),
// ★ 新增: 单条库存调整 // ★ 新增: 单条库存调整
adjustStock: (draftId: number, stockId: number, remark: string) => request({ adjustStock: (draftId: number, stockId: number, diffQty: number, sourceTable: string, remark: string) => request({
url: '/v1/inbound/stock/adjust', url: '/v1/inbound/stock/adjust',
method: 'post', method: 'post',
data: { data: {
draft_id: draftId, draft_id: draftId,
stock_id: stockId, // 备用参数 stock_id: stockId, // 库存项ID
operator_name: currentUser, diff_qty: diffQty, // 差异数量(支持无草稿模式)
remark: remark source_table: sourceTable, // 必须stock_buy / stock_semi / stock_product
operator_name: currentUser,
remark: remark
} }
}), }),
// ★ 保留清除功能(用于兼容性) // ★ 保留清除功能(用于兼容性)
@ -755,6 +757,10 @@ const closeOverlays = () => {
// --- 导出 Excel 逻辑 (调用后端API) --- // --- 导出 Excel 逻辑 (调用后端API) ---
const exportToExcel = async () => { const exportToExcel = async () => {
try { try {
// ===== 调试代码 =====
console.warn('---- 触发了导出 Excel ----');
// ===== 调试结束 =====
ElMessage.info('正在生成盘点报告,请稍候...'); ElMessage.info('正在生成盘点报告,请稍候...');
// 使用项目封装的 request 发送请求,确保自动携带 JWT Token // 使用项目封装的 request 发送请求,确保自动携带 JWT Token
const res: any = await request({ const res: any = await request({
@ -886,6 +892,12 @@ const openVarianceDialog = async () => {
// ★ 新增: 确认平账 // ★ 新增: 确认平账
const handleAdjust = async (row: any) => { const handleAdjust = async (row: any) => {
try { try {
// ===== 调试代码 =====
console.warn('---- 准备平账参数检查 ----');
console.warn('当前点击行的完整数据:', row);
console.warn(`将要发送的 draftId: ${row.id}, stockId: ${row.stock_id}, sourceTable: ${row.source_table}`);
// ===== 调试结束 =====
await ElMessageBox.confirm( await ElMessageBox.confirm(
`确定要对 "${row.uuid}" 进行平账调整吗?\n\n差异: ${row.diff_qty > 0 ? '盘盈 +' : '盘亏 '}${row.diff_qty}`, `确定要对 "${row.uuid}" 进行平账调整吗?\n\n差异: ${row.diff_qty > 0 ? '盘盈 +' : '盘亏 '}${row.diff_qty}`,
'确认平账', '确认平账',
@ -894,7 +906,7 @@ const handleAdjust = async (row: any) => {
const remark = `盘点差异调整 - ${row.diff_qty > 0 ? '盘盈入库' : '盘亏出库'}` const remark = `盘点差异调整 - ${row.diff_qty > 0 ? '盘盈入库' : '盘亏出库'}`
const res: any = await api.adjustStock(row.id, row.stock_id, remark) const res: any = await api.adjustStock(row.id, row.stock_id, row.diff_qty, row.source_table || 'stock_buy', remark)
ElMessage.success(res.message || '调整成功') ElMessage.success(res.message || '调整成功')