feat(outbound): 优化按 BOM 添加逻辑,支持缺件时按现有库存部分出库

This commit is contained in:
DXC
2026-04-21 13:06:03 +08:00
parent a5a35777b5
commit eba558c9d9

View File

@ -217,9 +217,8 @@
v-if="userStore.hasPermission('outbound_selection:operation')" v-if="userStore.hasPermission('outbound_selection:operation')"
type="primary" type="primary"
@click="confirmBomAdd" @click="confirmBomAdd"
:disabled="hasShortage"
> >
{{ hasShortage ? '库存不足,无法添加' : '一键计算并添加' }} {{ hasShortage ? '仅添加现有库存' : '确认添加' }}
</el-button> </el-button>
</template> </template>
</el-dialog> </el-dialog>
@ -632,50 +631,65 @@ watch(selectedBomNo, async (newBomNo) => {
}) })
const confirmBomAdd = async () => { const confirmBomAdd = async () => {
if(!selectedBomNo.value) return ElMessage.warning('请选择 BOM'); if (!selectedBomNo.value) return ElMessage.warning('请选择 BOM')
if (allStockData.value.length === 0) { if (allStockData.value.length === 0) {
await openManualSelect() await ensureAllStockLoaded()
manualDialogVisible.value = false
} }
try { if (currentBomDetail.value.length === 0) {
const detailRes = await getBomDetail(selectedBomNo.value) try {
const bomRows = detailRes.data?.children || [] const detailRes = await getBomDetail(selectedBomNo.value)
currentBomDetail.value = detailRes.data?.children || []
} catch (e) {
ElMessage.error('获取 BOM 详情失败')
return
}
}
let addedCount = 0; const bomRows = currentBomDetail.value
bomRows.forEach((bomItem: any) => { let addedCount = 0
const needQty = (parseFloat(bomItem.dosage) || 0) * bomSets.value let skippedCount = 0
// ★ BOM 添加时,匹配本地库存数据,带入库位信息
const stockCandidate = allStockData.value.find(s =>
(s.base_id && s.base_id == bomItem.child_id)
)
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) const existing = selectedItems.value.find(e => e.uniqueKey === stockCandidate.uniqueKey)
if (existing) { if (existing) {
existing.export_quantity += needQty existing.export_quantity += actualAddQty
} else { } else {
const newItem = JSON.parse(JSON.stringify(stockCandidate)) const newItem = JSON.parse(JSON.stringify(stockCandidate))
// 如果后端 BomService 也返回了 warehouse_location (聚合的),这里优先使用
if (bomItem.warehouse_location) { if (bomItem.warehouse_location) {
newItem.warehouse_location = bomItem.warehouse_location newItem.warehouse_location = bomItem.warehouse_location
} }
newItem.export_quantity = needQty newItem.export_quantity = actualAddQty
selectedItems.value.push(newItem) selectedItems.value.push(newItem)
} }
addedCount++ addedCount++
} else {
skippedCount++
} }
})
if(addedCount > 0) {
ElMessage.success(`成功添加 BOM 相关物料,共 ${addedCount}`)
bomSelectVisible.value = false
} else { } 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')
} }
} }