|
|
|
|
@ -51,7 +51,11 @@
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="调出库区" min-width="125">
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
<el-form-item :prop="`${$index}.fromAreaId`" :rules="formRules.fromAreaId" class="mb-0px!">
|
|
|
|
|
<el-form-item
|
|
|
|
|
:prop="`${$index}.fromAreaId`"
|
|
|
|
|
:rules="formRules.fromAreaId"
|
|
|
|
|
class="mb-0px!"
|
|
|
|
|
>
|
|
|
|
|
<el-select
|
|
|
|
|
v-model="row.fromAreaId"
|
|
|
|
|
clearable
|
|
|
|
|
@ -106,7 +110,12 @@
|
|
|
|
|
placeholder="请选择调入仓库"
|
|
|
|
|
@change="onChangeToWarehouse(row)"
|
|
|
|
|
>
|
|
|
|
|
<el-option v-for="item in getToWarehouseOptions(row)" :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>
|
|
|
|
|
@ -166,7 +175,12 @@
|
|
|
|
|
<el-button @click="handleAdd" round>+ 添加调拨产品</el-button>
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
<Dialog :title="productSelectTitle" v-model="productDialogVisible" width="900px" class="stock-move-product-dialog">
|
|
|
|
|
<Dialog
|
|
|
|
|
:title="productSelectTitle"
|
|
|
|
|
v-model="productDialogVisible"
|
|
|
|
|
width="900px"
|
|
|
|
|
class="stock-move-product-dialog"
|
|
|
|
|
>
|
|
|
|
|
<el-form :model="productQueryParams" :inline="true" class="-mb-15px">
|
|
|
|
|
<el-form-item :label="t('ErpStock.Item.code')">
|
|
|
|
|
<el-input
|
|
|
|
|
@ -193,20 +207,29 @@
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="productDialogLoading"
|
|
|
|
|
:data="productDialogList"
|
|
|
|
|
row-key="id"
|
|
|
|
|
:row-key="getProductOptionRowKey"
|
|
|
|
|
:stripe="true"
|
|
|
|
|
:show-overflow-tooltip="true"
|
|
|
|
|
@row-click="handleProductDialogRowClick"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column width="55" align="center">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-radio v-model="selectedProductId" :label="row.id"> </el-radio>
|
|
|
|
|
<el-radio v-model="selectedProductId" :label="getProductOptionId(row)"> </el-radio>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.code')" prop="barCode" min-width="160" />
|
|
|
|
|
<el-table-column :label="productColumnLabel" prop="name" min-width="160" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.spec')" prop="standard" min-width="120" />
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.category')" prop="subCategoryName" min-width="120" />
|
|
|
|
|
<el-table-column
|
|
|
|
|
:label="t('ErpStock.Item.category')"
|
|
|
|
|
prop="subCategoryName"
|
|
|
|
|
min-width="120"
|
|
|
|
|
/>
|
|
|
|
|
<el-table-column
|
|
|
|
|
:label="t('ErpStock.Stock.stockDisplay')"
|
|
|
|
|
prop="stockDisplay"
|
|
|
|
|
min-width="120"
|
|
|
|
|
/>
|
|
|
|
|
<el-table-column :label="t('ErpStock.Item.unit')" prop="unitName" min-width="80" />
|
|
|
|
|
</el-table>
|
|
|
|
|
<div class="product-dialog-pagination">
|
|
|
|
|
@ -229,6 +252,7 @@
|
|
|
|
|
import { ProductApi } from '@/api/erp/product/product'
|
|
|
|
|
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
|
|
|
|
|
import { StockMoveApi } from '@/api/erp/stock/move'
|
|
|
|
|
import { StockApi } from '@/api/erp/stock/stock'
|
|
|
|
|
import { erpCountInputFormatter, getSumValue } from '@/utils'
|
|
|
|
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
|
|
|
|
|
|
|
|
|
@ -245,17 +269,31 @@ const formData = ref<any[]>([])
|
|
|
|
|
const sameAreaMessage = '调出库区和调入库区不能相同'
|
|
|
|
|
const formRules = reactive({
|
|
|
|
|
inId: [{ required: true, message: '调度编号不能为空', trigger: 'submit' }],
|
|
|
|
|
fromWarehouseId: [{ required: true, message: t('ErpStock.Move.item.validatorFromWarehouseRequired'), trigger: 'submit' }],
|
|
|
|
|
fromWarehouseId: [
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t('ErpStock.Move.item.validatorFromWarehouseRequired'),
|
|
|
|
|
trigger: 'submit'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
fromAreaId: [
|
|
|
|
|
{ required: true, message: t('ErpStock.Item.validatorAreaRequired'), trigger: 'submit' },
|
|
|
|
|
{ validator: validateDifferentArea, trigger: ['change', 'submit'] }
|
|
|
|
|
],
|
|
|
|
|
toWarehouseId: [{ required: true, message: t('ErpStock.Move.item.validatorToWarehouseRequired'), trigger: 'submit' }],
|
|
|
|
|
toWarehouseId: [
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t('ErpStock.Move.item.validatorToWarehouseRequired'),
|
|
|
|
|
trigger: 'submit'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
toAreaId: [
|
|
|
|
|
{ required: true, message: t('ErpStock.Item.validatorAreaRequired'), trigger: 'submit' },
|
|
|
|
|
{ validator: validateDifferentArea, trigger: ['change', 'submit'] }
|
|
|
|
|
],
|
|
|
|
|
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'submit' }],
|
|
|
|
|
productId: [
|
|
|
|
|
{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'submit' }
|
|
|
|
|
],
|
|
|
|
|
count: [
|
|
|
|
|
{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'submit' },
|
|
|
|
|
{ validator: validateStockMoveCount, trigger: ['change', 'submit'] }
|
|
|
|
|
@ -269,11 +307,12 @@ const productDialogVisible = ref(false)
|
|
|
|
|
const productDialogLoading = ref(false)
|
|
|
|
|
const productDialogList = ref<any[]>([])
|
|
|
|
|
const productDialogTotal = ref(0)
|
|
|
|
|
const selectedProductId = ref<number>()
|
|
|
|
|
const selectedProductId = ref<number | string>()
|
|
|
|
|
const productQueryParams = reactive({
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
categoryType: undefined as number | undefined,
|
|
|
|
|
stockNotZero: true,
|
|
|
|
|
barCode: undefined as string | undefined,
|
|
|
|
|
name: undefined as string | undefined
|
|
|
|
|
})
|
|
|
|
|
@ -319,7 +358,9 @@ function getSummaries(param: SummaryMethodProps) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (column.property === 'count') {
|
|
|
|
|
sums[index] = erpCountInputFormatter(getSumValue(data.map((item) => Number(item[column.property]))))
|
|
|
|
|
sums[index] = erpCountInputFormatter(
|
|
|
|
|
getSumValue(data.map((item) => Number(item[column.property])))
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
sums[index] = ''
|
|
|
|
|
}
|
|
|
|
|
@ -359,7 +400,11 @@ function handleDelete(index) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isSameMoveArea(row) {
|
|
|
|
|
return row.fromAreaId !== undefined && row.toAreaId !== undefined && String(row.fromAreaId) === String(row.toAreaId)
|
|
|
|
|
return (
|
|
|
|
|
row.fromAreaId !== undefined &&
|
|
|
|
|
row.toAreaId !== undefined &&
|
|
|
|
|
String(row.fromAreaId) === String(row.toAreaId)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateDifferentArea(rule, _value, callback) {
|
|
|
|
|
@ -427,7 +472,9 @@ function warnIfSameArea(row) {
|
|
|
|
|
function validateAreaFields(row) {
|
|
|
|
|
const rowIndex = formData.value.indexOf(row)
|
|
|
|
|
if (rowIndex < 0) return
|
|
|
|
|
formRef.value?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`]).catch(() => undefined)
|
|
|
|
|
formRef.value
|
|
|
|
|
?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`])
|
|
|
|
|
.catch(() => undefined)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleFromAreaChange(row) {
|
|
|
|
|
@ -491,8 +538,9 @@ async function getProductDialogList() {
|
|
|
|
|
productDialogLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
productQueryParams.categoryType = props.categoryType
|
|
|
|
|
const data = await ProductApi.getProductPage(productQueryParams)
|
|
|
|
|
productDialogList.value = data?.list || []
|
|
|
|
|
productQueryParams.stockNotZero = true
|
|
|
|
|
const data = await StockApi.getStockPage(productQueryParams)
|
|
|
|
|
productDialogList.value = normalizeStockProductOptions(data?.list || [])
|
|
|
|
|
productDialogTotal.value = data?.total || 0
|
|
|
|
|
} finally {
|
|
|
|
|
productDialogLoading.value = false
|
|
|
|
|
@ -505,12 +553,14 @@ function handleProductDialogQuery() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleProductDialogRowClick(row: any) {
|
|
|
|
|
selectedProductId.value = row.id
|
|
|
|
|
selectedProductId.value = getProductOptionId(row)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function confirmProductSelect() {
|
|
|
|
|
if (props.disabled) return
|
|
|
|
|
const product = productDialogList.value.find((item) => item.id === selectedProductId.value)
|
|
|
|
|
const product = productDialogList.value.find(
|
|
|
|
|
(item) => String(getProductOptionId(item)) === String(selectedProductId.value)
|
|
|
|
|
)
|
|
|
|
|
if (!product || !currentSelectRow.value) return
|
|
|
|
|
fillRowByProduct(currentSelectRow.value, product)
|
|
|
|
|
await loadProductStockList(currentSelectRow.value)
|
|
|
|
|
@ -518,11 +568,11 @@ async function confirmProductSelect() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fillRowByProduct(row, product) {
|
|
|
|
|
row.productId = product.id
|
|
|
|
|
row.productName = product.name
|
|
|
|
|
row.productUnitName = product.unitName
|
|
|
|
|
row.productId = getProductOptionId(product)
|
|
|
|
|
row.productName = product.name || product.productName
|
|
|
|
|
row.productUnitName = product.unitName || product.purchaseUnitName
|
|
|
|
|
row.purchaseUnitName = product.purchaseUnitName
|
|
|
|
|
row.unitName = product.unitName
|
|
|
|
|
row.unitName = product.unitName || product.purchaseUnitName
|
|
|
|
|
row.productBarCode = product.barCode
|
|
|
|
|
row.fromWarehouseId = undefined
|
|
|
|
|
row.fromAreaId = undefined
|
|
|
|
|
@ -564,6 +614,34 @@ async function loadOptions() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getProductOptionId(item) {
|
|
|
|
|
return item?.productId ?? item?.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getProductOptionRowKey(row) {
|
|
|
|
|
return [getProductOptionId(row), row.warehouseId, row.areaId, row.stockId || row.id]
|
|
|
|
|
.filter((item) => item !== undefined && item !== null && item !== '')
|
|
|
|
|
.join('-')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeStockProductOptions(list) {
|
|
|
|
|
const map = new Map()
|
|
|
|
|
;(list || []).forEach((item) => {
|
|
|
|
|
const productId = getProductOptionId(item)
|
|
|
|
|
if (!productId || map.has(String(productId))) return
|
|
|
|
|
map.set(String(productId), {
|
|
|
|
|
...item,
|
|
|
|
|
id: productId,
|
|
|
|
|
productId,
|
|
|
|
|
name: item.name || item.productName,
|
|
|
|
|
unitName: item.unitName || item.purchaseUnitName,
|
|
|
|
|
subCategoryName: item.subCategoryName || item.categoryName,
|
|
|
|
|
stockDisplay: item.stockDisplay || item.totalBaseCount || item.count || item.stockCount
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
return Array.from(map.values())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeProductStockList(data) {
|
|
|
|
|
if (Array.isArray(data)) return data
|
|
|
|
|
if (Array.isArray(data?.list)) return data.list
|
|
|
|
|
@ -597,7 +675,9 @@ async function fillProductStockAreaInfo(stockList) {
|
|
|
|
|
stockList
|
|
|
|
|
.filter((item) => Number(getStockWarehouseId(item)) === Number(warehouseId))
|
|
|
|
|
.forEach((item) => {
|
|
|
|
|
const area = areaList.find((areaItem) => Number(areaItem.id) === Number(getStockAreaId(item)))
|
|
|
|
|
const area = areaList.find(
|
|
|
|
|
(areaItem) => Number(areaItem.id) === Number(getStockAreaId(item))
|
|
|
|
|
)
|
|
|
|
|
if (!area) return
|
|
|
|
|
item.areaCode = area.areaCode
|
|
|
|
|
item.areaName = area.areaName
|
|
|
|
|
@ -624,7 +704,9 @@ function getFromWarehouseOptions(row) {
|
|
|
|
|
return appendOptionIfMissing(
|
|
|
|
|
Array.from(warehouseMap.values()),
|
|
|
|
|
row.fromWarehouseId,
|
|
|
|
|
row.fromWarehouseName ? { warehouseId: row.fromWarehouseId, warehouseName: row.fromWarehouseName } : undefined,
|
|
|
|
|
row.fromWarehouseName
|
|
|
|
|
? { warehouseId: row.fromWarehouseId, warehouseName: row.fromWarehouseName }
|
|
|
|
|
: undefined,
|
|
|
|
|
getStockWarehouseId
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
@ -668,9 +750,11 @@ function getToWarehouseOptions(row) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getToAreaOptions(row) {
|
|
|
|
|
const areaOptions = Array.isArray(row.toAreaList) && row.toAreaList.length > 0
|
|
|
|
|
? row.toAreaList
|
|
|
|
|
: 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,
|
|
|
|
|
|