feat: add borrowed quantity column and update stocktake export formulas
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
@ -277,6 +277,8 @@ interface StockItem {
|
||||
type?: string
|
||||
category?: string
|
||||
price?: number
|
||||
source_table?: string
|
||||
stock_id?: number
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
@ -293,6 +295,7 @@ const showQtyDialog = ref(false)
|
||||
|
||||
const allData = ref<StockItem[]>([])
|
||||
const scannedMap = ref<Map<string, number>>(new Map())
|
||||
const borrowedQuantities = ref<Record<string, number>>({})
|
||||
|
||||
const filterType = ref('all')
|
||||
const searchKeyword = ref('')
|
||||
@ -307,6 +310,34 @@ const api = {
|
||||
clearDraft: () => request({ url: '/v1/inbound/stock/draft/clear', method: 'post', data: { user_id: currentUser } })
|
||||
}
|
||||
|
||||
const typeToSourceTable = (type: string): string => {
|
||||
switch (type) {
|
||||
case 'material': return 'stock_buy'
|
||||
case 'semi': return 'stock_semi'
|
||||
case 'product': return 'stock_product'
|
||||
default: return ''
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchBorrowedQuantities(items: StockItem[]): Promise<void> {
|
||||
const payload = items.filter(i => i.source_table && i.stock_id).map(i => ({
|
||||
source_table: i.source_table,
|
||||
stock_id: i.stock_id
|
||||
}))
|
||||
if (payload.length === 0) return
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/v1/inbound/stock/borrowed-quantities',
|
||||
method: 'post',
|
||||
data: { items: payload }
|
||||
})
|
||||
// res is map of key->qty
|
||||
borrowedQuantities.value = { ...borrowedQuantities.value, ...res }
|
||||
} catch (e) {
|
||||
console.error('获取借出数量失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await checkServerDraft()
|
||||
})
|
||||
@ -381,7 +412,9 @@ const loadData = async () => {
|
||||
qty_stock: stock,
|
||||
qty_actual: isScanned ? scannedMap.value.get(uuid)! : 0,
|
||||
scanned: isScanned,
|
||||
uniqueKey: `${type}_${item.id}`
|
||||
uniqueKey: `${type}_${item.id}`,
|
||||
source_table: typeToSourceTable(type),
|
||||
stock_id: item.id
|
||||
})
|
||||
}
|
||||
|
||||
@ -390,6 +423,7 @@ const loadData = async () => {
|
||||
if (res.products) res.products.forEach((i: any) => processItem(i, 'product'))
|
||||
|
||||
allData.value = list
|
||||
await fetchBorrowedQuantities(list)
|
||||
} catch (e) {
|
||||
ElMessage.error('数据加载失败')
|
||||
} finally { loading.value = false }
|
||||
@ -471,34 +505,47 @@ const closeOverlays = () => {
|
||||
const exportToExcel = () => {
|
||||
try {
|
||||
// 1. 已盘点 Sheet
|
||||
const scannedData = allData.value.filter(i => i.scanned).map(item => ({
|
||||
'物品名称': item.name,
|
||||
'类型': item.type || item.material_type || '-',
|
||||
'类别': item.category || '-',
|
||||
'规格型号': item.spec_model || item.standard || '-', // ★ 双重保险
|
||||
'SKU': item.sku,
|
||||
'批次/SN': item.serial_number || item.batch_no || '-',
|
||||
'单位': item.unit || '个',
|
||||
'单价': item.price || item.unit_price || 0,
|
||||
'账面库存': parseFloat(item.qty_stock as any),
|
||||
'实盘数量': item.qty_actual,
|
||||
'盘点结果': item.qty_stock === item.qty_actual ? '相符' : '差异',
|
||||
'差异数': item.qty_actual - item.qty_stock
|
||||
}))
|
||||
const scannedData = allData.value.filter(i => i.scanned).map(item => {
|
||||
const key = item.source_table && item.stock_id ? `${item.source_table}_${item.stock_id}` : ''
|
||||
const borrowedQty = borrowedQuantities.value[key] || 0
|
||||
const actualTotal = item.qty_actual + borrowedQty
|
||||
const diff = actualTotal - item.qty_stock
|
||||
const result = diff === 0 ? '正常' : diff < 0 ? '盘亏/差异' : '盘盈'
|
||||
return {
|
||||
'物品名称': item.name,
|
||||
'类型': item.type || item.material_type || '-',
|
||||
'类别': item.category || '-',
|
||||
'规格型号': item.spec_model || item.standard || '-', // ★ 双重保险
|
||||
'SKU': item.sku,
|
||||
'批次/SN': item.serial_number || item.batch_no || '-',
|
||||
'单位': item.unit || '个',
|
||||
'单价': item.price || item.unit_price || 0,
|
||||
'账面库存': parseFloat(item.qty_stock as any),
|
||||
'实盘数量': item.qty_actual,
|
||||
'借出未还数量': borrowedQty,
|
||||
'盘点结果': result,
|
||||
'差异数': diff
|
||||
}
|
||||
})
|
||||
|
||||
// 2. 未盘点 Sheet
|
||||
const missingData = allData.value.filter(i => !i.scanned).map(item => ({
|
||||
'物品名称': item.name,
|
||||
'类型': item.type || item.material_type || '-',
|
||||
'类别': item.category || '-',
|
||||
'规格型号': item.spec_model || item.standard || '-', // ★ 双重保险
|
||||
'SKU': item.sku,
|
||||
'批次/SN': item.serial_number || item.batch_no || '-',
|
||||
'单位': item.unit || '个',
|
||||
'单价': item.price || item.unit_price || 0,
|
||||
'账面库存': parseFloat(item.qty_stock as any),
|
||||
'状态': '未盘点'
|
||||
}))
|
||||
const missingData = allData.value.filter(i => !i.scanned).map(item => {
|
||||
const key = item.source_table && item.stock_id ? `${item.source_table}_${item.stock_id}` : ''
|
||||
const borrowedQty = borrowedQuantities.value[key] || 0
|
||||
return {
|
||||
'物品名称': item.name,
|
||||
'类型': item.type || item.material_type || '-',
|
||||
'类别': item.category || '-',
|
||||
'规格型号': item.spec_model || item.standard || '-', // ★ 双重保险
|
||||
'SKU': item.sku,
|
||||
'批次/SN': item.serial_number || item.batch_no || '-',
|
||||
'单位': item.unit || '个',
|
||||
'单价': item.price || item.unit_price || 0,
|
||||
'账面库存': parseFloat(item.qty_stock as any),
|
||||
'借出未还数量': borrowedQty,
|
||||
'状态': '未盘点'
|
||||
}
|
||||
})
|
||||
|
||||
const wb = XLSX.utils.book_new()
|
||||
const ws1 = XLSX.utils.json_to_sheet(scannedData)
|
||||
@ -507,7 +554,7 @@ const exportToExcel = () => {
|
||||
const wscols = [
|
||||
{wch: 20}, {wch: 10}, {wch: 10}, {wch: 15},
|
||||
{wch: 15}, {wch: 15}, {wch: 5}, {wch: 8},
|
||||
{wch: 8}, {wch: 8}, {wch: 8}, {wch: 8}
|
||||
{wch: 8}, {wch: 8}, {wch: 8}, {wch: 8}, {wch: 8}
|
||||
]
|
||||
ws1['!cols'] = wscols
|
||||
ws2['!cols'] = wscols
|
||||
|
||||
Reference in New Issue
Block a user