feat(outbound): 优化按 BOM 添加逻辑,支持缺件时按现有库存部分出库
This commit is contained in:
@ -213,13 +213,12 @@
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="bomSelectVisible = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="userStore.hasPermission('outbound_selection:operation')"
|
||||
type="primary"
|
||||
<el-button
|
||||
v-if="userStore.hasPermission('outbound_selection:operation')"
|
||||
type="primary"
|
||||
@click="confirmBomAdd"
|
||||
:disabled="hasShortage"
|
||||
>
|
||||
{{ hasShortage ? '库存不足,无法添加' : '一键计算并添加' }}
|
||||
{{ hasShortage ? '仅添加现有库存' : '确认添加' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -632,50 +631,65 @@ watch(selectedBomNo, async (newBomNo) => {
|
||||
})
|
||||
|
||||
const confirmBomAdd = async () => {
|
||||
if(!selectedBomNo.value) return ElMessage.warning('请选择 BOM');
|
||||
if (!selectedBomNo.value) return ElMessage.warning('请选择 BOM')
|
||||
|
||||
if (allStockData.value.length === 0) {
|
||||
await openManualSelect()
|
||||
manualDialogVisible.value = false
|
||||
await ensureAllStockLoaded()
|
||||
}
|
||||
|
||||
try {
|
||||
const detailRes = await getBomDetail(selectedBomNo.value)
|
||||
const bomRows = detailRes.data?.children || []
|
||||
if (currentBomDetail.value.length === 0) {
|
||||
try {
|
||||
const detailRes = await getBomDetail(selectedBomNo.value)
|
||||
currentBomDetail.value = detailRes.data?.children || []
|
||||
} catch (e) {
|
||||
ElMessage.error('获取 BOM 详情失败')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let addedCount = 0;
|
||||
bomRows.forEach((bomItem: any) => {
|
||||
const needQty = (parseFloat(bomItem.dosage) || 0) * bomSets.value
|
||||
// ★ BOM 添加时,匹配本地库存数据,带入库位信息
|
||||
const stockCandidate = allStockData.value.find(s =>
|
||||
(s.base_id && s.base_id == bomItem.child_id)
|
||||
)
|
||||
const bomRows = currentBomDetail.value
|
||||
let addedCount = 0
|
||||
let skippedCount = 0
|
||||
|
||||
if (stockCandidate) {
|
||||
bomRows.forEach((bomItem: any) => {
|
||||
const dosage = parseFloat(bomItem.dosage) || 0
|
||||
const needQty = dosage * bomSets.value
|
||||
|
||||
const stockCandidate = allStockData.value.find(s =>
|
||||
(s.base_id && s.base_id == bomItem.child_id)
|
||||
)
|
||||
|
||||
if (stockCandidate) {
|
||||
const availableQty = stockCandidate.availableCount || 0
|
||||
const actualAddQty = Math.min(needQty, availableQty)
|
||||
|
||||
if (actualAddQty > 0) {
|
||||
const existing = selectedItems.value.find(e => e.uniqueKey === stockCandidate.uniqueKey)
|
||||
if (existing) {
|
||||
existing.export_quantity += needQty
|
||||
existing.export_quantity += actualAddQty
|
||||
} else {
|
||||
const newItem = JSON.parse(JSON.stringify(stockCandidate))
|
||||
// 如果后端 BomService 也返回了 warehouse_location (聚合的),这里优先使用
|
||||
if (bomItem.warehouse_location) {
|
||||
newItem.warehouse_location = bomItem.warehouse_location
|
||||
}
|
||||
newItem.export_quantity = needQty
|
||||
newItem.export_quantity = actualAddQty
|
||||
selectedItems.value.push(newItem)
|
||||
}
|
||||
addedCount++
|
||||
} else {
|
||||
skippedCount++
|
||||
}
|
||||
})
|
||||
|
||||
if(addedCount > 0) {
|
||||
ElMessage.success(`成功添加 BOM 相关物料,共 ${addedCount} 类`)
|
||||
bomSelectVisible.value = false
|
||||
} else {
|
||||
ElMessage.warning('库存中未找到该 BOM 所需的任何原料')
|
||||
skippedCount++
|
||||
}
|
||||
} catch(e) {
|
||||
ElMessage.error('获取 BOM 详情失败')
|
||||
})
|
||||
|
||||
if (addedCount > 0) {
|
||||
const tip = skippedCount > 0 ? `(跳过 ${skippedCount} 种缺货物料)` : ''
|
||||
ElMessage.success(`成功添加 ${addedCount} 类物料${tip}`)
|
||||
bomSelectVisible.value = false
|
||||
} else {
|
||||
ElMessage.warning('该 BOM 所有物料库存均为 0')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user