|
|
|
|
@ -106,7 +106,7 @@
|
|
|
|
|
placeholder="请选择调入仓库"
|
|
|
|
|
@change="onChangeToWarehouse(row)"
|
|
|
|
|
>
|
|
|
|
|
<el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
<el-option v-for="item in getToWarehouseOptions(row)" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
@ -141,6 +141,7 @@
|
|
|
|
|
:min="0.001"
|
|
|
|
|
:precision="3"
|
|
|
|
|
class="!w-100%"
|
|
|
|
|
@change="handleCountChange(row)"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</template>
|
|
|
|
|
@ -255,7 +256,10 @@ const formRules = reactive({
|
|
|
|
|
{ validator: validateDifferentArea, trigger: ['change', 'submit'] }
|
|
|
|
|
],
|
|
|
|
|
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'submit' }],
|
|
|
|
|
count: [{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'submit' }]
|
|
|
|
|
count: [
|
|
|
|
|
{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'submit' },
|
|
|
|
|
{ validator: validateStockMoveCount, trigger: ['change', 'submit'] }
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
const formRef = ref()
|
|
|
|
|
const warehouseList = ref<WarehouseVO[]>([])
|
|
|
|
|
@ -365,6 +369,52 @@ function validateDifferentArea(rule, _value, callback) {
|
|
|
|
|
callback()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getNumberValue(value) {
|
|
|
|
|
if (value === undefined || value === null || value === '') return undefined
|
|
|
|
|
const numberValue = Number(String(value).replace(/,/g, ''))
|
|
|
|
|
return Number.isFinite(numberValue) ? numberValue : undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getCountExceededMessage(row) {
|
|
|
|
|
const stockCount = getNumberValue(row.stockCount)
|
|
|
|
|
return stockCount === undefined
|
|
|
|
|
? '调拨数量不能大于库存'
|
|
|
|
|
: `调拨数量不能大于库存(当前库存:${erpCountInputFormatter(stockCount)})`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isCountExceeded(row) {
|
|
|
|
|
const count = getNumberValue(row.count)
|
|
|
|
|
const stockCount = getNumberValue(row.stockCount)
|
|
|
|
|
return count !== undefined && stockCount !== undefined && count > stockCount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateStockMoveCount(rule, _value, callback) {
|
|
|
|
|
const rowIndex = Number(String(rule.field || '').split('.')[0])
|
|
|
|
|
const row = formData.value[rowIndex]
|
|
|
|
|
if (row && isCountExceeded(row)) {
|
|
|
|
|
callback(new Error(getCountExceededMessage(row)))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
callback()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function warnIfCountExceeded(row) {
|
|
|
|
|
if (isCountExceeded(row)) {
|
|
|
|
|
ElMessage.warning(getCountExceededMessage(row))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateCountField(row) {
|
|
|
|
|
const rowIndex = formData.value.indexOf(row)
|
|
|
|
|
if (rowIndex < 0) return
|
|
|
|
|
formRef.value?.validateField(`${rowIndex}.count`).catch(() => undefined)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleCountChange(row) {
|
|
|
|
|
warnIfCountExceeded(row)
|
|
|
|
|
validateCountField(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function warnIfSameArea(row) {
|
|
|
|
|
if (isSameMoveArea(row)) {
|
|
|
|
|
ElMessage.warning(sameAreaMessage)
|
|
|
|
|
@ -374,13 +424,15 @@ function warnIfSameArea(row) {
|
|
|
|
|
function validateAreaFields(row) {
|
|
|
|
|
const rowIndex = formData.value.indexOf(row)
|
|
|
|
|
if (rowIndex < 0) return
|
|
|
|
|
formRef.value?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`])
|
|
|
|
|
formRef.value?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`]).catch(() => undefined)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleFromAreaChange(row) {
|
|
|
|
|
await setStockCount(row)
|
|
|
|
|
warnIfSameArea(row)
|
|
|
|
|
validateAreaFields(row)
|
|
|
|
|
warnIfCountExceeded(row)
|
|
|
|
|
validateCountField(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleToAreaChange(row) {
|
|
|
|
|
@ -388,12 +440,14 @@ function handleToAreaChange(row) {
|
|
|
|
|
validateAreaFields(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onChangeFromWarehouse(_warehouseId, row) {
|
|
|
|
|
async function onChangeFromWarehouse(_warehouseId, row) {
|
|
|
|
|
const firstStock = getFromAreaOptions(row)[0]
|
|
|
|
|
row.fromAreaId = firstStock ? getStockAreaId(firstStock) : undefined
|
|
|
|
|
setStockCount(row)
|
|
|
|
|
await setStockCount(row)
|
|
|
|
|
warnIfSameArea(row)
|
|
|
|
|
validateAreaFields(row)
|
|
|
|
|
warnIfCountExceeded(row)
|
|
|
|
|
validateCountField(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function onChangeToWarehouse(row) {
|
|
|
|
|
@ -521,6 +575,8 @@ async function loadProductStockList(row) {
|
|
|
|
|
row.fromWarehouseId = firstStock ? getStockWarehouseId(firstStock) : undefined
|
|
|
|
|
row.fromAreaId = firstStock ? getStockAreaId(firstStock) : undefined
|
|
|
|
|
row.stockCount = firstStock ? getStockCount(firstStock) : undefined
|
|
|
|
|
warnIfCountExceeded(row)
|
|
|
|
|
validateCountField(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fillProductStockAreaInfo(stockList) {
|
|
|
|
|
@ -543,6 +599,12 @@ async function fillProductStockAreaInfo(stockList) {
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function appendOptionIfMissing(options, id, option, getId) {
|
|
|
|
|
if (id === undefined || id === null || !option) return options
|
|
|
|
|
const exists = options.some((item) => String(getId(item)) === String(id))
|
|
|
|
|
return exists ? options : [option, ...options]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getFromWarehouseOptions(row) {
|
|
|
|
|
const stockList = row.productStockList || []
|
|
|
|
|
const warehouseMap = new Map()
|
|
|
|
|
@ -552,41 +614,67 @@ function getFromWarehouseOptions(row) {
|
|
|
|
|
warehouseMap.set(warehouseId, item)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
return Array.from(warehouseMap.values())
|
|
|
|
|
return appendOptionIfMissing(
|
|
|
|
|
Array.from(warehouseMap.values()),
|
|
|
|
|
row.fromWarehouseId,
|
|
|
|
|
row.fromWarehouseName ? { warehouseId: row.fromWarehouseId, warehouseName: row.fromWarehouseName } : undefined,
|
|
|
|
|
getStockWarehouseId
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getFromAreaOptions(row) {
|
|
|
|
|
if (!row.fromWarehouseId) return []
|
|
|
|
|
return (row.productStockList || []).filter(
|
|
|
|
|
const areaOptions = (row.productStockList || []).filter(
|
|
|
|
|
(item) => Number(getStockWarehouseId(item)) === Number(row.fromWarehouseId)
|
|
|
|
|
)
|
|
|
|
|
return appendOptionIfMissing(
|
|
|
|
|
areaOptions,
|
|
|
|
|
row.fromAreaId,
|
|
|
|
|
row.fromAreaName ? { areaId: row.fromAreaId, areaName: row.fromAreaName } : undefined,
|
|
|
|
|
getStockAreaId
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStockWarehouseId(stock) {
|
|
|
|
|
return stock.warehouseId
|
|
|
|
|
return stock.warehouseId ?? stock.fromWarehouseId ?? stock.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStockWarehouseName(stock) {
|
|
|
|
|
return stock.warehouseName || stock.name || stock.warehouseId
|
|
|
|
|
return stock.warehouseName || stock.fromWarehouseName || stock.name || getStockWarehouseId(stock)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStockAreaId(stock) {
|
|
|
|
|
return stock.areaId
|
|
|
|
|
return stock.areaId ?? stock.fromAreaId ?? stock.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStockCount(stock) {
|
|
|
|
|
return stock.stockCount ?? stock.count
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getToWarehouseOptions(row) {
|
|
|
|
|
return appendOptionIfMissing(
|
|
|
|
|
warehouseList.value,
|
|
|
|
|
row.toWarehouseId,
|
|
|
|
|
row.toWarehouseName ? { id: row.toWarehouseId, name: row.toWarehouseName } : undefined,
|
|
|
|
|
(item) => item.id
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getToAreaOptions(row) {
|
|
|
|
|
if (Array.isArray(row.toAreaList) && row.toAreaList.length > 0) return row.toAreaList
|
|
|
|
|
return warehouseList.value.find((item) => Number(item.id) === Number(row.toWarehouseId))?.areaList || []
|
|
|
|
|
const areaOptions = Array.isArray(row.toAreaList) && row.toAreaList.length > 0
|
|
|
|
|
? row.toAreaList
|
|
|
|
|
: warehouseList.value.find((item) => Number(item.id) === Number(row.toWarehouseId))?.areaList || []
|
|
|
|
|
return appendOptionIfMissing(
|
|
|
|
|
areaOptions,
|
|
|
|
|
row.toAreaId,
|
|
|
|
|
row.toAreaName ? { id: row.toAreaId, areaName: row.toAreaName } : undefined,
|
|
|
|
|
(item) => item.id
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getAreaLabel(item) {
|
|
|
|
|
const areaCode = item.areaCode || item.code
|
|
|
|
|
const areaName = item.areaName || item.name
|
|
|
|
|
const areaName = item.areaName || item.fromAreaName || item.toAreaName || item.name
|
|
|
|
|
return areaCode ? `${areaCode} - ${areaName || ''}` : areaName
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -607,6 +695,10 @@ async function setStockCount(row) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validate() {
|
|
|
|
|
const exceededRow = formData.value.find(isCountExceeded)
|
|
|
|
|
if (exceededRow) {
|
|
|
|
|
ElMessage.warning(getCountExceededMessage(exceededRow))
|
|
|
|
|
}
|
|
|
|
|
return formRef.value.validate()
|
|
|
|
|
}
|
|
|
|
|
defineExpose({ validate })
|
|
|
|
|
|