Compare commits

4 Commits

3 changed files with 26 additions and 17 deletions

View File

@ -214,12 +214,16 @@ def delete_bom(bom_no):
if version: if version:
query = query.filter_by(version=version) query = query.filter_by(version=version)
exist = query.first() # 【核心修复】:使用 .all() 查出该 BOM 版本下的所有子件记录
if not exist: records = query.all()
if not records:
return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404 return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404
# 删除(改为对象级删除以触发审计事件 # 循环删除所有关联记录(逐个 delete 可触发 SQLAlchemy 监听器记录审计日志
db.session.delete(exist) for rec in records:
db.session.delete(rec)
db.session.commit() db.session.commit()
return jsonify({ return jsonify({
'code': 200, 'code': 200,

View File

@ -325,11 +325,22 @@ def get_drafts():
total = len(items) total = len(items)
start = (page - 1) * limit start = (page - 1) * limit
end = start + limit end = start + limit
# 计算真实的去重"已盘数量"
counted_items_set = set()
for draft_item in items:
# 兼容判断 quantity 或 qty_actual
if draft_item.get('quantity') is not None or draft_item.get('qty_actual') is not None:
unique_key = f"{draft_item.get('source_table', '')}_{draft_item.get('stock_id', '')}"
counted_items_set.add(unique_key)
total_scanned_unique = len(counted_items_set)
paginated_items = items[start:end] paginated_items = items[start:end]
return jsonify({ return jsonify({
'items': paginated_items, 'items': paginated_items,
'total': total, 'total': total,
'total_scanned': total_scanned_unique,
'page': page, 'page': page,
'limit': limit 'limit': limit
}), 200 }), 200

View File

@ -486,6 +486,7 @@ const listData = ref<any[]>([])
const listStatusFilter = ref<'all' | 'counted' | 'uncounted'>('all') const listStatusFilter = ref<'all' | 'counted' | 'uncounted'>('all')
const allStockItems = ref<any[]>([]) // 全量应盘物资(盘点基数) const allStockItems = ref<any[]>([]) // 全量应盘物资(盘点基数)
const totalStockCount = ref(0) // ★ 全量应盘物资总数不受limit限制 const totalStockCount = ref(0) // ★ 全量应盘物资总数不受limit限制
const totalScannedCount = ref(0) // ★ 后端去重的真实已盘数量
const allScannedDrafts = ref<any[]>([]) // 全量草稿记录(脱离分页和过滤) const allScannedDrafts = ref<any[]>([]) // 全量草稿记录(脱离分页和过滤)
const listTotalFiltered = ref(0) // 过滤后的总数 const listTotalFiltered = ref(0) // 过滤后的总数
@ -515,18 +516,9 @@ const stats = computed(() => {
const total = allStockItems.value.length const total = allStockItems.value.length
if (total === 0) return { total: 0, scanned: 0, varianceItems: 0 } if (total === 0) return { total: 0, scanned: 0, varianceItems: 0 }
// 使用完整的 allScannedDrafts 来计算"已盘"数量,绝对不依赖视图数据
const countedItems = new Set()
allScannedDrafts.value.forEach((d: any) => {
// 只要有实盘记录就算已盘
if (d.quantity !== undefined && d.quantity !== null) {
countedItems.add(`${d.source_table}-${d.stock_id}`)
}
})
return { return {
total, total,
scanned: countedItems.size, scanned: totalScannedCount.value,
varianceItems: 0 varianceItems: 0
} }
}) })
@ -665,7 +657,7 @@ const resumeSession = async () => {
const res: any = await request({ const res: any = await request({
url: '/v1/inbound/stock/draft/list', url: '/v1/inbound/stock/draft/list',
method: 'get', method: 'get',
params: { page: 1, limit: 500 } // ★ 限制单次加载数量,防止内存溢出 params: { page: 1, limit: 99999 } // ★ 获取全量草稿数据
}) })
const drafts = res && res.items ? res.items : [] const drafts = res && res.items ? res.items : []
@ -993,7 +985,7 @@ const fetchInventoryList = async (silent = false) => {
method: 'get', method: 'get',
params: { params: {
page: 1, page: 1,
limit: 500, // ★ 限制单次加载数量,防止内存溢出 limit: 99999, // ★ 获取全量草稿数据
keyword: listKeyword.value, keyword: listKeyword.value,
session_id: currentSessionId.value // ★ 必须传递 session_id 隔离会话 session_id: currentSessionId.value // ★ 必须传递 session_id 隔离会话
} }
@ -1005,6 +997,8 @@ const fetchInventoryList = async (silent = false) => {
// 保存全量草稿记录用于全局统计 // 保存全量草稿记录用于全局统计
allScannedDrafts.value = scannedDrafts allScannedDrafts.value = scannedDrafts
// 直接读取后端算好的去重已盘数
totalScannedCount.value = res?.total_scanned || 0
// 2. 使用全量应盘物资列表 // 2. 使用全量应盘物资列表
// 对于每个应盘物资,检查是否有对应的盘点记录 // 对于每个应盘物资,检查是否有对应的盘点记录
@ -1023,7 +1017,7 @@ const fetchInventoryList = async (silent = false) => {
material_name: item.material_name, material_name: item.material_name,
spec_model: item.spec_model, spec_model: item.spec_model,
stock_qty: item.stock_qty, // 账面数(盲盘时隐藏) stock_qty: item.stock_qty, // 账面数(盲盘时隐藏)
quantity: draft?.quantity || 0, // 实盘数 quantity: draft?.quantity ?? draft?.qty_actual ?? 0, // 兼容后端字段名
diff_qty: draft ? (draft.quantity - item.stock_qty) : -item.stock_qty, // 差异 diff_qty: draft ? (draft.quantity - item.stock_qty) : -item.stock_qty, // 差异
remark: draft?.remark || '', remark: draft?.remark || '',
warehouse_location: item.warehouse_location warehouse_location: item.warehouse_location