Commit f7de2ca4 by yubin

导入bug修改

parent 2c73e2a2
......@@ -71,6 +71,7 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 仓库查询相关已注释 -->
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="queryWarehouseName"
......@@ -220,16 +221,18 @@
<div><strong>拣货区:</strong>{{ scope.row.pickingArea || '-' }}</div>
</el-col>
</el-row>
<el-row :gutter="20" style="margin: 10px 0;">
<!-- 允许存放物料名称已注释 -->
<!-- <el-row :gutter="20" style="margin: 10px 0;">
<el-col :span="24">
<div><strong>允许存放物料名称:</strong>{{ scope.row.allowedCategoryNames || '-' }}</div>
</el-col>
</el-row>
</el-row> -->
</template>
</el-table-column>
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="库位编码" align="center" prop="locationCode" min-width="120" fixed />
<el-table-column label="库位名称" align="center" prop="locationName" min-width="150" />
<!-- 仓库列已注释 -->
<!-- <el-table-column label="仓库" align="center" prop="warehousesName" width="180">
<template slot-scope="scope">
{{ scope.row.warehousesName }}
......@@ -263,7 +266,8 @@
<el-table-column label="库位容量(千克)" align="center" prop="capacity" min-width="120" />
<el-table-column label="体积容量(立方米)" align="center" prop="volumeCapacity" min-width="120" />
<el-table-column label="允许存放的危险等级" align="center" prop="allowedHazardLevels" min-width="140" />
<el-table-column label="允许存放的物料名称" align="center" prop="allowedCategoryNames" min-width="200">
<!-- 允许存放物料名称列已注释 -->
<!-- <el-table-column label="允许存放的物料名称" align="center" prop="allowedCategoryNames" min-width="200">
<template slot-scope="scope">
<el-tooltip
:content="scope.row.allowedCategoryNames"
......@@ -293,7 +297,7 @@
</div>
</el-tooltip>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column label="温区" align="center" prop="temperatureZone" width="100" />
<el-table-column label="应用状态" align="center" prop="isEnabled" width="100">
<template slot-scope="scope">
......@@ -357,6 +361,7 @@
</el-form-item>
</el-col>
</el-row>
<!-- 仓库表单项已注释 -->
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="form.warehouseName"
......@@ -510,7 +515,8 @@
<el-input v-model="form.allowedHazardLevels" placeholder="请输入允许存放的危险等级" />
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 允许存放物料表单项已注释 -->
<!-- <el-col :span="12">
<el-form-item label="允许存放物料" prop="allowedCategoryIds">
<div style="display: flex; align-items: center; flex-direction: column; gap: 8px;">
<el-input
......@@ -522,7 +528,7 @@
/>
</div>
</el-form-item>
</el-col>
</el-col> -->
</el-row>
<el-row :gutter="20">
<el-col :span="12">
......@@ -549,8 +555,8 @@
</div>
</el-dialog>
<!-- 选择允许存放的物料对话框 -->
<el-dialog
<!-- 选择允许存放的物料对话框已注释 -->
<!-- <el-dialog
title="选择允许存放的物料"
:visible.sync="showMaterialSelect"
width="1000px"
......@@ -570,7 +576,7 @@
<el-button @click="handleMaterialSelectionCancel">取消</el-button>
<el-button type="primary" @click="confirmMaterialSelection">确认选择</el-button>
</div>
</el-dialog>
</el-dialog> -->
<!-- 导入组件 -->
<import-excel
......@@ -582,7 +588,7 @@
@success="getList"
/>
<!-- 仓库选择器组件 -->
<!-- 仓库选择器组件已注释 -->
<!-- <WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
......@@ -592,15 +598,19 @@
<script>
import { listLocations, getLocations, delLocations, addLocations, updateLocations } from "@/api/inventory/locations"
import { listWarehouses } from "@/api/inventory/warehouses"
import materialsSeletor from "../../../components/materialsSeletor.vue"
// 仓库相关API已注释
// import { listWarehouses } from "@/api/inventory/warehouses"
// 物料选择器组件已注释
// import materialsSeletor from "../../../components/materialsSeletor.vue"
// import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import ImportExcel from "@/components/ImportExcel/index"
import { listMaterials } from "@/api/inventory/materials"
// 物料相关API已注释
// import { listMaterials } from "@/api/inventory/materials"
export default {
name: "Locations",
components: { materialsSeletor, ImportExcel },
// 组件注册已注释物料选择器
components: { /* materialsSeletor, */ ImportExcel },
dicts: ['sys_normal_disable', 'location_type', 'location_usage', 'yorn','is_enabled'],
data() {
return {
......@@ -620,7 +630,8 @@ export default {
pageSize: 10,
locationCode: null,
locationName: null,
warehouseId: null,
// 仓库查询参数已注释
// warehouseId: null,
locationType: null,
layerCode: null,
locationUsage: null,
......@@ -634,8 +645,9 @@ export default {
id: null,
locationCode: null,
locationName: null,
warehouseId: null,
warehouseName: null,
// 仓库相关字段已注释
// warehouseId: null,
// warehouseName: null,
locationType: null,
zoneCode: null,
rowCode: null,
......@@ -644,8 +656,9 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
allowedCategoryIds: null, // 原materialCodes
allowedCategoryNames: null, // 原materialNames
// 物料分类相关字段已注释
// allowedCategoryIds: null, // 原materialCodes
// allowedCategoryNames: null, // 原materialNames
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
......@@ -670,6 +683,7 @@ export default {
{ required: true, message: '库位名称不能为空', trigger: 'blur' },
{ min: 1, max: 100, message: '库位名称长度不能超过100个字符', trigger: 'blur' }
],
// 仓库验证规则已注释
// warehouseId: [
// { required: true, message: '仓库不能为空', trigger: 'change' }
// ],
......@@ -690,170 +704,172 @@ export default {
]
},
// 仓库相关
warehouseList: [],
loadingWarehouse: false,
queryWarehouseName: '',
// 物料选择相关
showMaterialSelect: false,
tempSelectedMaterials: {
materialCodes: [],
names: [],
categoryIds: []
},
materialCodeToNameMap: {},
materialMapLoaded: false,
// 仓库选择器相关
warehouseSelectorVisible: false,
warehouseSelectTarget: '',
// 仓库相关数据已注释
// warehouseList: [],
// loadingWarehouse: false,
// queryWarehouseName: '',
// 物料选择相关数据已注释
// showMaterialSelect: false,
// tempSelectedMaterials: {
// materialCodes: [],
// names: [],
// categoryIds: []
// },
// materialCodeToNameMap: {},
// materialMapLoaded: false,
// 仓库选择器相关数据已注释
// warehouseSelectorVisible: false,
// warehouseSelectTarget: '',
currentDetailItem: null
}
},
created() {
console.log('【Locations组件】开始初始化')
this.getList()
this.getWarehouseList()
this.initMaterialCodeToNameMap()
// 仓库列表加载已注释
// this.getWarehouseList()
// 物料映射表初始化已注释
// this.initMaterialCodeToNameMap()
},
methods: {
// ========== 新增:初始化物料选择器(核心修复数据残留) ==========
initMaterialSelector() {
console.log('【初始化物料选择器】清空残留数据')
// 1. 清空临时选择数据(区分新增/修改)
this.tempSelectedMaterials = {
materialCodes: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : []) : [],
names: this.form.id ? (this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : []) : [],
categoryIds: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []) : []
}
// 2. 延迟打开弹窗,确保数据先清空
this.$nextTick(() => {
this.showMaterialSelect = true
// 3. 兼容子组件清空选中状态(如果有该方法)
if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
this.$refs.materialsSeletor.clearSelection()
// 修改模式下重新设置选中值
if (this.form.id) {
this.$refs.materialsSeletor.setSelection(this.tempSelectedMaterials.materialCodes)
}
}
})
},
// 清空查询仓库
clearQueryWarehouse() {
console.log('【清空查询仓库】执行清空操作')
this.queryWarehouseName = ''
this.queryParams.warehouseId = null
this.handleQuery()
},
// 清空表单仓库
clearFormWarehouse() {
console.log('【清空表单仓库】执行清空操作')
this.form.warehouseName = ''
this.form.warehouseId = null
},
// 仓库选择回调
handleWarehouseSelected(warehouse) {
console.log('【仓库选择回调】选中的仓库数据:', warehouse)
if (!warehouse) return
const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id
const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName
if (this.warehouseSelectTarget === 'query') {
this.queryParams.warehouseId = warehouseId
this.queryWarehouseName = warehouseName
this.handleQuery()
} else {
this.form.warehouseId = warehouseId
this.form.warehouseName = warehouseName
if (this.currentDetailItem) {
this.currentDetailItem.warehouseId = warehouseId
this.currentDetailItem.warehouseName = warehouseName
}
}
this.warehouseSelectorVisible = false
},
// 打开仓库选择器
openWarehouseSelector(target = 'form') {
console.log('【打开仓库选择器】目标:', target)
this.warehouseSelectTarget = target
this.warehouseSelectorVisible = true
},
// 获取仓库列表
getWarehouseList() {
console.log('【获取仓库列表】开始请求仓库数据')
this.loadingWarehouse = true
listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => {
console.log('【获取仓库列表】请求成功,返回数据:', response)
this.warehouseList = response.rows || []
this.loadingWarehouse = false
}).catch(error => {
console.error('【获取仓库列表】请求失败:', error)
this.warehouseList = []
this.loadingWarehouse = false
})
},
// 根据仓库ID获取仓库名称
getWarehouseNameById(warehouseId) {
console.log('【根据仓库ID获取名称】仓库ID:', warehouseId)
if (!warehouseId) return '-'
const warehouse = this.warehouseList.find(item =>
item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId
)
const warehouseName = warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-'
console.log('【根据仓库ID获取名称】匹配到的仓库名称:', warehouseName)
return warehouseName
},
// 初始化物料编码-名称映射表
async initMaterialCodeToNameMap() {
console.log('【初始化物料映射表】开始加载物料数据')
try {
this.materialMapLoaded = true
let pageNum = 1
const pageSize = 1000
let hasMore = true
this.materialCodeToNameMap = {}
while (hasMore) {
console.log(`【初始化物料映射表】请求第${pageNum}页物料数据,每页${pageSize}条`)
const response = await listMaterials({
pageNum,
pageSize,
isUsed: 1,
materialCode: null,
materialName: null
})
if (response.rows && response.rows.length) {
console.log(`【初始化物料映射表】第${pageNum}页返回${response.rows.length}条物料数据`)
response.rows.forEach(item => {
if (item.materialCode && item.materialName) {
const code = item.materialCode.trim().toUpperCase()
this.materialCodeToNameMap[code] = item.materialName
}
})
hasMore = pageNum * pageSize < response.total
pageNum++
} else {
hasMore = false
}
}
console.log('【初始化物料映射表】完成,映射表长度:', Object.keys(this.materialCodeToNameMap).length)
} catch (error) {
console.error('【初始化物料映射表】失败:', error)
this.materialMapLoaded = false
this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
}
},
// 物料选择器初始化已注释
// initMaterialSelector() {
// console.log('【初始化物料选择器】清空残留数据')
// // 1. 清空临时选择数据(区分新增/修改)
// this.tempSelectedMaterials = {
// materialCodes: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : []) : [],
// names: this.form.id ? (this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : []) : [],
// categoryIds: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []) : []
// }
// // 2. 延迟打开弹窗,确保数据先清空
// this.$nextTick(() => {
// this.showMaterialSelect = true
// // 3. 兼容子组件清空选中状态(如果有该方法)
// if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
// this.$refs.materialsSeletor.clearSelection()
// // 修改模式下重新设置选中值
// if (this.form.id) {
// this.$refs.materialsSeletor.setSelection(this.tempSelectedMaterials.materialCodes)
// }
// }
// })
// },
// 清空查询仓库已注释
// clearQueryWarehouse() {
// console.log('【清空查询仓库】执行清空操作')
// this.queryWarehouseName = ''
// this.queryParams.warehouseId = null
// this.handleQuery()
// },
// 清空表单仓库已注释
// clearFormWarehouse() {
// console.log('【清空表单仓库】执行清空操作')
// this.form.warehouseName = ''
// this.form.warehouseId = null
// },
// 仓库选择回调已注释
// handleWarehouseSelected(warehouse) {
// console.log('【仓库选择回调】选中的仓库数据:', warehouse)
// if (!warehouse) return
// const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id
// const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName
// if (this.warehouseSelectTarget === 'query') {
// this.queryParams.warehouseId = warehouseId
// this.queryWarehouseName = warehouseName
// this.handleQuery()
// } else {
// this.form.warehouseId = warehouseId
// this.form.warehouseName = warehouseName
// if (this.currentDetailItem) {
// this.currentDetailItem.warehouseId = warehouseId
// this.currentDetailItem.warehouseName = warehouseName
// }
// }
// this.warehouseSelectorVisible = false
// },
// 打开仓库选择器已注释
// openWarehouseSelector(target = 'form') {
// console.log('【打开仓库选择器】目标:', target)
// this.warehouseSelectTarget = target
// this.warehouseSelectorVisible = true
// },
// 获取仓库列表已注释
// getWarehouseList() {
// console.log('【获取仓库列表】开始请求仓库数据')
// this.loadingWarehouse = true
// listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => {
// console.log('【获取仓库列表】请求成功,返回数据:', response)
// this.warehouseList = response.rows || []
// this.loadingWarehouse = false
// }).catch(error => {
// console.error('【获取仓库列表】请求失败:', error)
// this.warehouseList = []
// this.loadingWarehouse = false
// })
// },
// 根据仓库ID获取仓库名称已注释
// getWarehouseNameById(warehouseId) {
// console.log('【根据仓库ID获取名称】仓库ID:', warehouseId)
// if (!warehouseId) return '-'
// const warehouse = this.warehouseList.find(item =>
// item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId
// )
// const warehouseName = warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-'
// console.log('【根据仓库ID获取名称】匹配到的仓库名称:', warehouseName)
// return warehouseName
// },
// 初始化物料编码-名称映射表已注释
// async initMaterialCodeToNameMap() {
// console.log('【初始化物料映射表】开始加载物料数据')
// try {
// this.materialMapLoaded = true
// let pageNum = 1
// const pageSize = 1000
// let hasMore = true
// this.materialCodeToNameMap = {}
// while (hasMore) {
// console.log(`【初始化物料映射表】请求第${pageNum}页物料数据,每页${pageSize}条`)
// const response = await listMaterials({
// pageNum,
// pageSize,
// isUsed: 1,
// materialCode: null,
// materialName: null
// })
// if (response.rows && response.rows.length) {
// console.log(`【初始化物料映射表】第${pageNum}页返回${response.rows.length}条物料数据`)
// response.rows.forEach(item => {
// if (item.materialCode && item.materialName) {
// const code = item.materialCode.trim().toUpperCase()
// this.materialCodeToNameMap[code] = item.materialName
// }
// })
// hasMore = pageNum * pageSize < response.total
// pageNum++
// } else {
// hasMore = false
// }
// }
// console.log('【初始化物料映射表】完成,映射表长度:', Object.keys(this.materialCodeToNameMap).length)
// } catch (error) {
// console.error('【初始化物料映射表】失败:', error)
// this.materialMapLoaded = false
// this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
// }
// },
// 行点击事件
handleRowClick(row, event, column) {
......@@ -870,7 +886,8 @@ export default {
const params = {
...this.queryParams,
isUsed: 1,
warehousesId: this.queryParams.warehouseId,
// 仓库ID参数已注释
// warehousesId: this.queryParams.warehouseId,
warehouseId: undefined
}
console.log('【获取库位列表】最终请求参数:', params)
......@@ -902,7 +919,8 @@ export default {
pageSize: 10,
locationCode: null,
locationName: null,
warehouseId: null,
// 仓库查询参数已注释
// warehouseId: null,
locationType: null,
layerCode: null,
locationUsage: null,
......@@ -910,7 +928,8 @@ export default {
zoneCode: null,
pickingArea: null
}
this.queryWarehouseName = ''
// 仓库名称重置已注释
// this.queryWarehouseName = ''
this.getList()
},
......@@ -950,73 +969,76 @@ export default {
// 映射后端字段到前端
const formData = {
...rowData,
warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id,
// 仓库相关字段映射已注释
// warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id,
warehousesId: undefined
}
this.form = JSON.parse(JSON.stringify(formData))
// 设置仓库名称
if (this.form.warehouseId) {
this.form.warehouseName = this.getWarehouseNameById(this.form.warehouseId)
}
// 设置仓库名称已注释
// if (this.form.warehouseId) {
// this.form.warehouseName = this.getWarehouseNameById(this.form.warehouseId)
// }
await this.initMaterialCodeToNameMap()
// 物料映射表初始化已注释
// await this.initMaterialCodeToNameMap()
// 物料相关处理已注释
// 处理物料编码和名称(支持数组或字符串格式)
let materialCodes = []
let materialNames = []
// 优先从allowedCategoryIds数组读取(原materialIds)
if (Array.isArray(rowData.allowedCategoryIds) && rowData.allowedCategoryIds.length) {
materialCodes = rowData.allowedCategoryIds
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
}
// 兼容字符串格式
else if (rowData.allowedCategoryIds) {
materialCodes = rowData.allowedCategoryIds.split(',')
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
}
// 处理物料名称
if (Array.isArray(rowData.allowedCategoryNames) && rowData.allowedCategoryNames.length) {
materialNames = rowData.allowedCategoryNames
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
}
else if (rowData.allowedCategoryNames) {
materialNames = rowData.allowedCategoryNames.split(',')
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
}
// 兜底:通过物料编码映射名称
else if (materialCodes.length) {
materialNames = materialCodes.map(code => {
return this.materialCodeToNameMap[code] || `【未匹配】${code}`
})
}
// 处理分类ID(现在存储的是物料编码)
let categoryIds = materialCodes
// 更新表单数据
this.form.allowedCategoryIds = materialCodes.join(',')
this.form.allowedCategoryNames = materialNames.join(',')
// 更新临时选择数据
this.tempSelectedMaterials = {
materialCodes: materialCodes,
names: materialNames,
categoryIds: categoryIds
}
console.log('【修改库位】处理后的物料数据:', {
allowedCategoryIds: this.form.allowedCategoryIds,
allowedCategoryNames: this.form.allowedCategoryNames
})
// let materialCodes = []
// let materialNames = []
// // 优先从allowedCategoryIds数组读取(原materialIds)
// if (Array.isArray(rowData.allowedCategoryIds) && rowData.allowedCategoryIds.length) {
// materialCodes = rowData.allowedCategoryIds
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// }
// // 兼容字符串格式
// else if (rowData.allowedCategoryIds) {
// materialCodes = rowData.allowedCategoryIds.split(',')
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// }
// // 处理物料名称
// if (Array.isArray(rowData.allowedCategoryNames) && rowData.allowedCategoryNames.length) {
// materialNames = rowData.allowedCategoryNames
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// }
// else if (rowData.allowedCategoryNames) {
// materialNames = rowData.allowedCategoryNames.split(',')
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// }
// // 兜底:通过物料编码映射名称
// else if (materialCodes.length) {
// materialNames = materialCodes.map(code => {
// return this.materialCodeToNameMap[code] || `【未匹配】${code}`
// })
// }
// // 处理分类ID(现在存储的是物料编码)
// let categoryIds = materialCodes
// // 更新表单数据
// this.form.allowedCategoryIds = materialCodes.join(',')
// this.form.allowedCategoryNames = materialNames.join(',')
// // 更新临时选择数据
// this.tempSelectedMaterials = {
// materialCodes: materialCodes,
// names: materialNames,
// categoryIds: categoryIds
// }
// console.log('【修改库位】处理后的物料数据:', {
// allowedCategoryIds: this.form.allowedCategoryIds,
// allowedCategoryNames: this.form.allowedCategoryNames
// })
this.open = true
this.title = "修改库位"
......@@ -1032,24 +1054,26 @@ export default {
this.$refs["form"].validate(valid => {
if (valid) {
console.log('【提交表单】表单验证通过,开始格式化数据')
// 物料字段格式化已注释
// 格式化物料相关字段(去重、过滤空值)
const formatField = (value) => {
if (!value) return ''
const result = value.split(',')
.filter(item => item && item.trim())
.filter((item, index, self) => self.indexOf(item) === index)
.join(',')
console.log(`【提交表单】格式化字段值 "${value}" 结果: "${result}"`)
return result
}
this.form.allowedCategoryIds = formatField(this.form.allowedCategoryIds)
this.form.allowedCategoryNames = formatField(this.form.allowedCategoryNames)
// const formatField = (value) => {
// if (!value) return ''
// const result = value.split(',')
// .filter(item => item && item.trim())
// .filter((item, index, self) => self.indexOf(item) === index)
// .join(',')
// console.log(`【提交表单】格式化字段值 "${value}" 结果: "${result}"`)
// return result
// }
// this.form.allowedCategoryIds = formatField(this.form.allowedCategoryIds)
// this.form.allowedCategoryNames = formatField(this.form.allowedCategoryNames)
// 转换表单数据
const submitData = {
...this.form,
warehousesId: this.form.warehouseId,
// 仓库ID映射已注释
// warehousesId: this.form.warehouseId,
warehouseId: undefined,
warehouseName: undefined
}
......@@ -1100,76 +1124,77 @@ export default {
console.log('【导出库位】执行导出操作,查询参数:', this.queryParams)
const exportParams = {
...this.queryParams,
warehousesId: this.queryParams.warehouseId,
// 仓库ID参数已注释
// warehousesId: this.queryParams.warehouseId,
warehouseId: undefined
}
console.log('【导出库位】最终导出参数:', exportParams)
this.download('inventory/locations/export', exportParams, `locations_${new Date().getTime()}.xlsx`)
},
// 物料选择变化
handleMaterialSelectionChange(selectedData) {
console.log('【物料选择变化】接收到的选择数据:', selectedData)
// 修复:从selectedData中取materialIds(而非materialCodes)
const materialCodes = (selectedData.materialIds || [])
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
// 物料名称取selectedData.names
const names = (selectedData.names || [])
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
// 分类ID取selectedData.categoryIds(现在存储的是物料编码)
const categoryIds = materialCodes
this.tempSelectedMaterials = {
materialCodes,
names,
categoryIds
}
console.log('【物料选择变化】处理后的临时选择数据:', this.tempSelectedMaterials)
},
// 取消物料选择
handleMaterialSelectionCancel() {
console.log('【取消物料选择】执行取消操作,恢复原有选择状态')
this.showMaterialSelect = false
// 恢复原有选择状态
this.tempSelectedMaterials = {
materialCodes: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : [],
names: this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : [],
categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
}
console.log('【取消物料选择】恢复后的临时选择数据:', this.tempSelectedMaterials)
},
// 确认物料选择
confirmMaterialSelection() {
console.log('【确认物料选择】当前临时选择数据:', this.tempSelectedMaterials)
// 修复:判断tempSelectedMaterials.materialCodes是否有值
if (!this.tempSelectedMaterials.materialCodes.length) {
console.warn('【确认物料选择】未选择任何物料,提示用户')
this.$modal.msgWarning('请至少选择一个物料!')
return
}
// 更新表单数据(确保去重和过滤)
this.form.allowedCategoryIds = this.tempSelectedMaterials.materialCodes.join(',')
this.form.allowedCategoryNames = this.tempSelectedMaterials.names.join(',')
console.log('【确认物料选择】更新后的表单物料数据:', {
allowedCategoryIds: this.form.allowedCategoryIds,
allowedCategoryNames: this.form.allowedCategoryNames
})
this.showMaterialSelect = false
this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
},
// 物料选择变化已注释
// handleMaterialSelectionChange(selectedData) {
// console.log('【物料选择变化】接收到的选择数据:', selectedData)
// // 修复:从selectedData中取materialIds(而非materialCodes)
// const materialCodes = (selectedData.materialIds || [])
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// // 物料名称取selectedData.names
// const names = (selectedData.names || [])
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// // 分类ID取selectedData.categoryIds(现在存储的是物料编码)
// const categoryIds = materialCodes
// this.tempSelectedMaterials = {
// materialCodes,
// names,
// categoryIds
// }
// console.log('【物料选择变化】处理后的临时选择数据:', this.tempSelectedMaterials)
// },
// 取消物料选择已注释
// handleMaterialSelectionCancel() {
// console.log('【取消物料选择】执行取消操作,恢复原有选择状态')
// this.showMaterialSelect = false
// // 恢复原有选择状态
// this.tempSelectedMaterials = {
// materialCodes: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : [],
// names: this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : [],
// categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
// }
// console.log('【取消物料选择】恢复后的临时选择数据:', this.tempSelectedMaterials)
// },
// 确认物料选择已注释
// confirmMaterialSelection() {
// console.log('【确认物料选择】当前临时选择数据:', this.tempSelectedMaterials)
// // 修复:判断tempSelectedMaterials.materialCodes是否有值
// if (!this.tempSelectedMaterials.materialCodes.length) {
// console.warn('【确认物料选择】未选择任何物料,提示用户')
// this.$modal.msgWarning('请至少选择一个物料!')
// return
// }
// // 更新表单数据(确保去重和过滤)
// this.form.allowedCategoryIds = this.tempSelectedMaterials.materialCodes.join(',')
// this.form.allowedCategoryNames = this.tempSelectedMaterials.names.join(',')
// console.log('【确认物料选择】更新后的表单物料数据:', {
// allowedCategoryIds: this.form.allowedCategoryIds,
// allowedCategoryNames: this.form.allowedCategoryNames
// })
// this.showMaterialSelect = false
// this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
// },
// 导入库位
handleImport() {
......@@ -1184,8 +1209,9 @@ export default {
id: null,
locationCode: null,
locationName: null,
warehouseId: null,
warehouseName: null,
// 仓库相关字段已注释
// warehouseId: null,
// warehouseName: null,
locationType: null,
zoneCode: null,
rowCode: null,
......@@ -1194,8 +1220,9 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
allowedCategoryIds: null, // 原materialCodes
allowedCategoryNames: null, // 原materialNames
// 物料分类相关字段已注释
// allowedCategoryIds: null, // 原materialCodes
// allowedCategoryNames: null, // 原materialNames
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
......@@ -1209,15 +1236,16 @@ export default {
allowMixedProducts: null,
allowMixedBatches: null
}
this.tempSelectedMaterials = {
materialCodes: [],
names: [],
categoryIds: []
}
// 修复:清空物料选择器残留
if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
this.$refs.materialsSeletor.clearSelection()
}
// 物料临时数据重置已注释
// this.tempSelectedMaterials = {
// materialCodes: [],
// names: [],
// categoryIds: []
// }
// 物料选择器清空已注释
// if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
// this.$refs.materialsSeletor.clearSelection()
// }
if (this.$refs.form) {
this.$refs.form.resetFields()
}
......@@ -1277,4 +1305,4 @@ export default {
max-width: 300px;
white-space: normal;
}
</style>
</style>
\ No newline at end of file
......@@ -78,23 +78,27 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="出库类型" prop="orderTypeId">
<el-input
v-model="queryParams.orderTypeId"
placeholder="请输入出库类型"
<!-- 【保留位置】时间段选择器固定在第三个位置 -->
<el-form-item label="时间段" prop="dateRange">
<el-date-picker
clearable
@keyup.enter.native="handleQuery"
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
style="width: 100%"
/>
</el-form-item>
<!-- 新增:订单类型查询项 -->
<el-form-item label="订单类型" prop="orderType">
<el-select
v-model="queryParams.orderType"
placeholder="请选择订单类型"
<el-form-item label="出库类型" prop="orderTypeId">
<el-select
v-model="queryParams.orderTypeId"
placeholder="请输入出库类型"
clearable
style="width: 100%"
>
<el-option
<el-option
v-for="dict in dict.type.inbound_outbound_type"
:key="dict.value"
:label="dict.label"
......@@ -102,6 +106,7 @@
/>
</el-select>
</el-form-item>
<el-form-item label="批次" prop="batchCode">
<el-input
v-model="queryParams.batchCode"
......@@ -110,19 +115,6 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 【核心修改1】出库日期改为时间段选择器 -->
<el-form-item label="时间段" prop="dateRange">
<el-date-picker
clearable
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="订单状态" prop="orderStatus">
<el-select
v-model="queryParams.orderStatus"
......@@ -617,7 +609,7 @@ export default {
warehouseId: null,
ownerId: null,
orderStatus: null,
dateRange: null, // 日期范围选择器绑定
dateRange: null, // 日期范围选择器绑定(固定在第三个搜索位置)
startDate: null, // 开始日期
endDate: null, // 结束日期
destination: null,
......@@ -1241,7 +1233,7 @@ export default {
warehouseId: null,
ownerId: null,
orderStatus: null,
dateRange: null, // 重置日期范围
dateRange: null, // 重置日期范围(固定在第三个位置)
startDate: null,
endDate: null,
destination: null,
......
......@@ -24,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
......@@ -35,6 +34,7 @@ import java.util.stream.Collectors;
* 3. 无库位明细拆分精准匹配实际扣减的库存ID+数量
* 4. 缓存与数据库实时同步,解决数据不一致问题
* 5. 合并/扣减/拆分逻辑完全对齐维度,杜绝数据错乱
* 6. 核心:扣减哪个库存ID就提取哪个,精准赋值到明细
*
* @author ruoyi
* @date 2025-12-03
......@@ -187,11 +187,11 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 核心库存扣减逻辑(最终适配版
* 1. 扣减维度:物料ID+库存类型+库位ID
* 2. 相同维度多库存:按数量从多到少遍历扣减,支持全部扣完
* 3. 无库位→有库位:自动匹配所有可用库位库存,精准扣减
* 4. 扣减记录按单库存ID生成,支持后续明细精准拆分
* 核心库存扣减逻辑(精准提取被扣减的库存ID
* 核心:扣减哪个库存ID就提取哪个,仅保留实际被扣减的ID
*/
/**
* 核心库存扣减逻辑(确保每个明细仅对应一个库存ID)
*/
private Map<String, List<Map<String, Object>>> deductInventory(List<OutboundOrderItems> outboundOrderItems, String updateUser, Date updateTime) {
if (CollectionUtils.isEmpty(outboundOrderItems)) {
......@@ -199,11 +199,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
Map<String, List<Map<String, Object>>> deductRecordMap = new HashMap<>();
// 预加载库存:按「物料ID+库存类型+库位ID」分组,保存所有库存对象
Map<String, List<Inventory>> inventoryGroupMap = this.loadInventoryGroupMap();
Map<String, Long> deductQtyMap = this.buildDeductQtyMap(outboundOrderItems);
// 库存更新Map(最终去重,保留最终状态)
Map<String, Inventory> toUpdateInventoryMap = new LinkedHashMap<>();
for (Map.Entry<String, Long> entry : deductQtyMap.entrySet()) {
......@@ -222,15 +219,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
.orElse(null);
Long remainDeductQty = totalDeductQty;
// 核心:按维度分组扣减(先无库位,后有库位)
List<Map<String, Object>> tempDeductRecords = new ArrayList<>();
if (StringUtils.isBlank(locationId)) {
// 步骤1:扣无库位库存(同维度所有库存)
String noLocKey = buildInventoryKey(materialId, "", inventoryType);
remainDeductQty = deductByInventoryGroup(noLocKey, remainDeductQty, updateUser, updateTime, inventoryGroupMap, toUpdateInventoryMap, tempDeductRecords);
// 步骤2:无库位不足,扣同物料+库存类型的所有有库位库存
if (remainDeductQty > 0) {
List<String> hasLocKeys = inventoryGroupMap.keySet().stream()
.filter(k -> {
......@@ -242,7 +236,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
})
.collect(Collectors.toList());
// 有库位库存按总数量从多到少排序(优先扣减库存充足的库位)
hasLocKeys.sort((k1, k2) -> {
Long qty1 = inventoryGroupMap.get(k1).stream().mapToLong(inv -> Optional.ofNullable(inv.getQuantity()).orElse(0L)).sum();
Long qty2 = inventoryGroupMap.get(k2).stream().mapToLong(inv -> Optional.ofNullable(inv.getQuantity()).orElse(0L)).sum();
......@@ -255,12 +248,10 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
}
} else {
// 有库位:扣指定维度库存
String targetKey = buildInventoryKey(materialId, locationId, inventoryType);
remainDeductQty = deductByInventoryGroup(targetKey, remainDeductQty, updateUser, updateTime, inventoryGroupMap, toUpdateInventoryMap, tempDeductRecords);
}
// 步骤3:剩余数量强制扣减(允许库存负数)
if (remainDeductQty > 0 && !tempDeductRecords.isEmpty()) {
Map<String, Object> lastRecord = tempDeductRecords.get(tempDeductRecords.size() - 1);
String lastInvId = (String) lastRecord.get("inventoryId");
......@@ -269,34 +260,28 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
throw new ServiceException(String.format("物料[%s]库存类型[%s]扣减负数时未找到目标库存", materialId, inventoryType));
}
// 累计扣减负数数量
lastInv.setQuantity(lastInv.getQuantity() - remainDeductQty);
lastInv.setInventoryStatus(0L);
lastInv.setUpdateBy(updateUser);
lastInv.setUpdateTime(updateTime);
toUpdateInventoryMap.put(lastInvId, lastInv);
// 更新扣减记录
lastRecord.put("deductQty", (Long) lastRecord.get("deductQty") + remainDeductQty);
remainDeductQty = 0L;
}
// 步骤4:按明细ID归集扣减记录(不合并,保持单库存ID粒度)
if (itemId != null && !tempDeductRecords.isEmpty()) {
deductRecordMap.put(itemId, tempDeductRecords);
}
// 校验扣减完成
if (remainDeductQty > 0) {
throw new ServiceException(String.format("物料[%s]库存类型[%s]扣减失败,剩余%d数量未扣减", materialId, inventoryType, remainDeductQty));
}
}
// 批量更新库存 + 刷新缓存
if (!toUpdateInventoryMap.isEmpty()) {
List<Inventory> needUpdateList = new ArrayList<>(toUpdateInventoryMap.values());
inventoryMapper.batchUpdateInventory(needUpdateList);
// 刷新缓存:删除旧缓存,重新加载
needUpdateList.forEach(inv -> {
String cacheKey = buildInventoryKey(inv.getMaterialId(), inv.getLocationId(), inv.getInventoryType().toString());
InventoryCache.removeInventory(cacheKey, inv.getId());
......@@ -304,13 +289,105 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
});
}
// 核心修改:不再拼接ID,而是直接拆分为单ID明细
splitToSingleInvIdItems(outboundOrderItems, deductRecordMap, updateUser, updateTime);
return deductRecordMap;
}
private void splitToSingleInvIdItems(List<OutboundOrderItems> oldItems, Map<String, List<Map<String, Object>>> deductRecordMap, String updateUser, Date updateTime) {
if (CollectionUtils.isEmpty(oldItems) || CollectionUtils.isEmpty(deductRecordMap)) {
return;
}
List<OutboundOrderItems> newSingleItems = new ArrayList<>();
Set<String> orderIdSet = new HashSet<>();
for (OutboundOrderItems oldItem : oldItems) {
String oldItemId = oldItem.getId();
List<Map<String, Object>> deductRecords = deductRecordMap.get(oldItemId);
if (CollectionUtils.isEmpty(deductRecords)) {
continue;
}
orderIdSet.add(oldItem.getOutboundOrderId());
// 每一条扣减记录对应一个新明细(单库存ID)
for (Map<String, Object> rec : deductRecords) {
String inventoryId = (String) rec.get("inventoryId");
String locationId = (String) rec.get("locationId");
Long deductQty = (Long) rec.get("deductQty");
if (deductQty <= 0 || StringUtils.isBlank(inventoryId)) {
continue;
}
OutboundOrderItems newItem = new OutboundOrderItems();
BeanUtils.copyProperties(oldItem, newItem);
newItem.setId(UUID.randomUUID().toString().replace("-", "")); // 新主键
newItem.setInventoryId(inventoryId); // 仅单个库存ID(无逗号)
newItem.setLocationId(locationId); // 同步库位
newItem.setActualQuantity(deductQty); // 仅当前库存ID的扣减数量
newItem.setUpdateBy(updateUser);
newItem.setUpdateTime(updateTime);
newSingleItems.add(newItem);
}
}
// 删除原明细,插入拆分后的单ID明细
if (!orderIdSet.isEmpty() && !newSingleItems.isEmpty()) {
// 1. 删除原明细
orderIdSet.forEach(orderId -> outboundOrderItemsMapper.deleteOutboundOrderItemsByOrderId(orderId));
// 2. 插入单ID明细
outboundOrderItemsMapper.batchInsertOutboundOrderItems(newSingleItems);
// 3. 更新日志(同步单ID明细)
List<OutboundOrderLog> logList = newSingleItems.stream().map(item -> {
OutboundOrderLog log = new OutboundOrderLog();
BeanUtils.copyProperties(item, log);
log.setOrderId(item.getOutboundOrderId());
log.setItemStatus(3L);
return log;
}).collect(Collectors.toList());
outboundOrderLogMapper.batchOutboundOrderLog(logList);
}
}
/**
* 为所有明细回填实际被扣减的inventoryId(仅保留被扣减的ID)
* @param items 出库明细列表
* @param deductRecordMap 扣减记录Map(itemId → 实际扣减的库存ID列表)
*/
private void fillInventoryIdToItems(List<OutboundOrderItems> items, Map<String, List<Map<String, Object>>> deductRecordMap) {
if (CollectionUtils.isEmpty(items) || CollectionUtils.isEmpty(deductRecordMap)) {
return;
}
for (OutboundOrderItems item : items) {
String itemId = item.getId();
List<Map<String, Object>> deductRecords = deductRecordMap.get(itemId);
if (CollectionUtils.isEmpty(deductRecords)) {
continue;
}
// 仅收集当前明细实际被扣减的库存ID(去重,无冗余)
List<String> deductedInventoryIds = deductRecords.stream()
.map(rec -> (String) rec.get("inventoryId"))
.filter(StringUtils::isNotBlank)
.distinct()
.collect(Collectors.toList());
// 仅赋值实际被扣减的库存ID
if (!deductedInventoryIds.isEmpty()) {
item.setInventoryId(String.join(",", deductedInventoryIds));
// 同步更新数据库,确保持久化
outboundOrderItemsMapper.updateOutboundOrderItems(item);
}
}
}
/**
* 按维度分组扣减库存(核心适配:遍历同维度所有库存
* 按维度分组扣减库存(核心:扣哪个库存ID就记录哪个
* @param inventoryKey 维度Key
* @param deductQty 待扣减数量
* @param tempDeductRecords 仅记录实际被扣减的库存ID
* @return 剩余未扣减数量
*/
private Long deductByInventoryGroup(String inventoryKey, Long deductQty, String updateUser, Date updateTime,
......@@ -321,7 +398,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
return deductQty;
}
// 同维度库存按数量从多到少排序(优先扣减数量多的,减少拆分次数
// 同维度库存按数量从多到少排序(优先扣减数量多的)
invList.sort((a, b) -> {
Long qtyA = Optional.ofNullable(a.getQuantity()).orElse(0L);
Long qtyB = Optional.ofNullable(b.getQuantity()).orElse(0L);
......@@ -332,17 +409,18 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
for (Inventory inv : invList) {
if (remainDeduct <= 0) break;
String currentInvId = inv.getId(); // 提取当前要扣减的库存ID
Long currentQty = Optional.ofNullable(inv.getQuantity()).orElse(0L);
Long canDeduct = Math.min(remainDeduct, currentQty);
Long canDeduct = Math.min(remainDeduct, currentQty); // 实际扣减数量
// 更新库存对象
inv.setQuantity(currentQty - canDeduct);
inv.setInventoryStatus(inv.getQuantity() > 0 ? 1L : 0L);
inv.setUpdateBy(updateUser);
inv.setUpdateTime(updateTime);
toUpdateInventoryMap.put(inv.getId(), inv);
toUpdateInventoryMap.put(currentInvId, inv);
// 生成单库存ID的扣减记录(关键:不再合并库存ID
// 仅记录当前被扣减的库存ID(扣哪个记哪个
Map<String, Object> record = buildDeductRecord(inv, inv.getInventoryType().toString(), canDeduct);
tempDeductRecords.add(record);
......@@ -353,29 +431,27 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 构建扣减记录(单库存ID粒度
* 构建扣减记录(仅包含实际被扣减的库存ID
*/
private Map<String, Object> buildDeductRecord(Inventory inv, String inventoryType, Long deductQty) {
Map<String, Object> record = new HashMap<>();
record.put("inventoryId", inv.getId());
record.put("inventoryId", inv.getId()); // 仅记录实际被扣减的库存ID
record.put("locationId", inv.getLocationId());
record.put("materialId", inv.getMaterialId());
record.put("inventoryType", inventoryType);
record.put("deductQty", deductQty);
record.put("deductQty", deductQty); // 该库存ID实际被扣减的数量
return record;
}
/**
* 预加载库存分组Map(按维度Key分组,保存所有库存对象
* 预加载库存分组Map(按维度Key分组)
*/
private Map<String, List<Inventory>> loadInventoryGroupMap() {
// 1. 用你现有的selectInventoryList查全量可用库存(传空条件=查所有)
Inventory query = new Inventory();
query.setInventoryStatus(1L); // 只查可用状态库存
query.setIsUsed(1L); // 只查启用的库存
List<Inventory> allInventory = inventoryMapper.selectInventoryList(query);
// 2. 按维度分组(和你原有逻辑完全一致)
Map<String, List<Inventory>> inventoryGroupMap = new LinkedHashMap<>();
for (Inventory inv : allInventory) {
String key = buildInventoryKey(
......@@ -455,7 +531,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
throw new RuntimeException("库存被修改请重新确认");
}
// 合并相同维度明细(仅合并数量,库存ID不拼接
// 合并相同维度明细(仅合并数量,不拼接库存ID
List<OutboundOrderItems> mergedItemsList = mergeSameInventoryItems(outboundOrderItemsList);
// 为明细设置订单ID和主键ID
......@@ -476,7 +552,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
BeanUtils.copyProperties(items, log);
log.setOrderId(items.getOutboundOrderId());
outboundOrderLogs.add(log);
// 拆分库存ID(支持逗号分隔)
// 仅拆分实际被扣减的库存ID
if (StringUtils.isNotBlank(items.getInventoryId())) {
String[] invIds = items.getInventoryId().split(",");
for (String invId : invIds) {
......@@ -724,16 +800,17 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
// ========== 关键修改:移除 CompletableFuture 异步执行,改为同步调用 ==========
// 8. 同步执行库存扣减和无库位明细拆分(原异步逻辑改为同步
// 8. 同步执行库存扣减和无库位明细拆分(仅处理实际被扣减的库存ID
try {
for (Map.Entry<String, List<OutboundOrderItems>> entry : allItemListMap.entrySet()) {
List<OutboundOrderItems> itemList = entry.getValue();
// 执行库存扣减
// 执行库存扣减(精准提取被扣减的库存ID)
Map<String, List<Map<String, Object>>> deductRecordMap = deductInventory(itemList, operId, now);
// 处理无库位明细拆分
// 处理无库位明细拆分(仅拆分实际被扣减的库存ID)
handleNoLocationItemSplit(itemList, deductRecordMap, operId, now);
}
} catch (Exception e) {
// 可添加日志记录异常
}
// 9. 结果汇总
......@@ -753,7 +830,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 处理无库位明细拆分(精准匹配扣减记录
* 处理无库位明细拆分(仅拆分实际被扣减的库存ID
*/
private void handleNoLocationItemSplit(List<OutboundOrderItems> itemList,
Map<String, List<Map<String, Object>>> deductRecordMap,
......@@ -763,14 +840,14 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
for (OutboundOrderItems item : itemList) {
if (StringUtils.isNotBlank(item.getLocationId())) {
continue; // 跳过有库位明细
continue; // 跳过有库位明细(已赋值实际被扣减的库存ID)
}
String itemId = item.getId();
List<Map<String, Object>> deductRecords = deductRecordMap.get(itemId);
if (CollectionUtils.isEmpty(deductRecords)) continue;
orderIdSet.add(item.getOutboundOrderId());
// 按扣减记录拆分明细(一条扣减记录对应一条新明细)
// 仅按实际被扣减的库存ID拆分明细
for (Map<String, Object> rec : deductRecords) {
String inventoryId = (String) rec.get("inventoryId");
String locId = (String) rec.get("locationId");
......@@ -783,19 +860,19 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
newItem.setId(UUID.randomUUID().toString().replace("-", ""));
newItem.setLocationId(locId);
newItem.setActualQuantity(deductQty);
newItem.setInventoryId(inventoryId);
newItem.setInventoryId(inventoryId); // 仅赋值实际被扣减的单个库存ID
newItem.setUpdateBy(operId);
newItem.setUpdateTime(now);
newItemList.add(newItem);
}
}
// 删除原无库位明细,插入拆分后的新明细
// 删除原无库位明细,插入拆分后的新明细(仅包含实际被扣减的库存ID)
if (!orderIdSet.isEmpty() && !newItemList.isEmpty()) {
orderIdSet.forEach(orderId -> outboundOrderItemsMapper.deleteOutboundOrderItemsByOrderId(orderId));
outboundOrderItemsMapper.batchInsertOutboundOrderItems(newItemList);
// 生成拆分后的日志
// 生成拆分后的日志(仅包含实际被扣减的库存ID)
List<OutboundOrderLog> logList = newItemList.stream().map(item -> {
OutboundOrderLog log = new OutboundOrderLog();
BeanUtils.copyProperties(item, log);
......
......@@ -36,10 +36,11 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
{
@Autowired
private StorageLocationsMapper storageLocationsMapper;
@Autowired
private StorageLocationsCategoryMapper storageLocationsCategoryMapper;
@Autowired
private MaterialsMapper materialsMapper;
// 注释掉关联mapper(如果不需要可直接删除)
// @Autowired
// private StorageLocationsCategoryMapper storageLocationsCategoryMapper;
// @Autowired
// private MaterialsMapper materialsMapper;
/**
* 查询库位
......@@ -51,7 +52,8 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
public StorageLocations selectStorageLocationsById(String id)
{
StorageLocations storageLocations = storageLocationsMapper.selectStorageLocationsById(id);
String AllowedCategoryName = "";
// 注释掉物料反显逻辑
/*String AllowedCategoryName = "";
if (storageLocations.getAllowedCategoryIds() != null) {
String[] AllowedCategoryIds = storageLocations.getAllowedCategoryIds().split(",");
if (AllowedCategoryIds != null && AllowedCategoryIds.length > 0) {
......@@ -67,7 +69,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
}
}
}
storageLocations.setAllowedCategoryNames(AllowedCategoryName);
storageLocations.setAllowedCategoryNames(AllowedCategoryName);*/
return storageLocations;
}
......@@ -91,7 +93,8 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
public List<StorageLocations> selectStorageLocationsList(StorageLocations storageLocations)
{
List<StorageLocations> storageLocations1 = storageLocationsMapper.selectStorageLocationsList(storageLocations);
for (StorageLocations storageLocations2 : storageLocations1){
// 注释掉物料反显逻辑
/*for (StorageLocations storageLocations2 : storageLocations1){
String AllowedCategoryName = "";
if (storageLocations2.getAllowedCategoryIds() != null && !storageLocations2.getAllowedCategoryIds().isEmpty()){
String[] AllowedCategoryIds = storageLocations2.getAllowedCategoryIds().split(",");
......@@ -107,7 +110,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
}
}
storageLocations2.setAllowedCategoryNames(AllowedCategoryName);
}
}*/
return storageLocations1;
}
......@@ -122,14 +125,15 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
{
storageLocations.setCreateTime(DateUtils.getNowDate());
StorageLocationsCategory storageLocationsCategory = new StorageLocationsCategory();
BeanUtils.copyBeanProp(storageLocationsCategory,storageLocations);
// 注释掉所有库位分类关联逻辑
/*StorageLocationsCategory storageLocationsCategory = new StorageLocationsCategory();
BeanUtils.copyBeanProp(storageLocationsCategory,storageLocations);*/
String LocationsID = UUID.randomUUID().toString();
storageLocations.setId(LocationsID);
storageLocations.setCreateTime(DateUtils.getNowDate());
storageLocations.setCreateUserCode(String.valueOf(SecurityUtils.getUserId()));
storageLocations.setWarehousesId(WarehouseConfig.DEFAULT_WAREHOUSE_ID);
storageLocationsCategory.setLocationCode(LocationsID);
/*storageLocationsCategory.setLocationCode(LocationsID);
if (storageLocations.getAllowedCategoryIds() != null && !storageLocations.getAllowedCategoryIds().isEmpty()){
......@@ -143,7 +147,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
storageLocationsCategory.setCategoryName(materials.getMaterialName());
storageLocationsCategoryMapper.insertStorageLocationsCategory(storageLocationsCategory);
}
}
}*/
return storageLocationsMapper.insertStorageLocations(storageLocations);
}
......@@ -162,7 +166,8 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
String LocationsID = storageLocations.getId();
String LocationsCode = storageLocations.getLocationCode();
StorageLocations storageLocations1 = storageLocationsMapper.selectStorageLocationsById(LocationsID);
if (storageLocations1.getAllowedCategoryIds()!=storageLocations.getAllowedCategoryIds()||storageLocations1.getIsEnabled()!=storageLocations.getIsEnabled()){
// 注释掉库位分类关联修改逻辑
/*if (storageLocations1.getAllowedCategoryIds()!=storageLocations.getAllowedCategoryIds()||storageLocations1.getIsEnabled()!=storageLocations.getIsEnabled()){
storageLocationsCategoryMapper.deleteStorageLocationsCategoryByLocationCode(LocationsID);
String[] CategoryId = storageLocations.getAllowedCategoryIds().split(",");
......@@ -179,7 +184,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
storageLocationsCategory.setCategoryName(materials.getMaterialName());
storageLocationsCategoryMapper.insertStorageLocationsCategory(storageLocationsCategory);
}
}
}*/
return storageLocationsMapper.updateStorageLocations(storageLocations);
}
......@@ -205,14 +210,14 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
@Override
public int deleteStorageLocationsById(String id)
{
storageLocationsCategoryMapper.deleteStorageLocationsCategoryById(id);
// 注释掉关联的库位分类删除逻辑
// storageLocationsCategoryMapper.deleteStorageLocationsCategoryById(id);
return storageLocationsMapper.deleteStorageLocationsById(id);
}
@Override
public int updateLocationsCategoryStatus(String id)
{
return storageLocationsMapper.updateStorageLocationsStatus(id);
}
......@@ -329,4 +334,4 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
}
return successMsg.toString();
}
}
}
\ No newline at end of file
......@@ -97,7 +97,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.is_serial_managed,
m.min_stock_level,
m.max_stock_level,
IFNULL(i.quantity-locked_quantity, 0) as stock, -- 无库存时默认显示0
IFNULL(stock_sum.total_stock, 0) as stock,
m.is_used,
m.is_active,
m.risk_level,
......@@ -107,7 +107,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.update_time,
m.update_user_code
from materials m
left join inventory i on m.id = i.material_id
left join (
select
material_id,
SUM(quantity - locked_quantity) as total_stock
from inventory
group by material_id
) stock_sum on m.id = stock_sum.material_id
<where>
m.is_used = 1
<if test="materialCode != null and materialCode != ''"> and m.material_code like concat('%', #{materialCode}, '%')</if>
......@@ -135,8 +141,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sortNo != null "> and m.sort_no = #{sortNo}</if>
<if test="createTime != null "> and m.create_time like concat('%', #{createTime}, '%')</if>
<if test="updateTime != null "> and m.update_time like concat('%', #{updateTime}, '%')</if>
-- 可选:添加库存数量的查询条件(如果需要)
<if test="stock != null "> and i.stock = #{stock}</if>
<if test="stock != null "> and stock_sum.total_stock = #{stock}</if>
</where>
order by stock desc
</select>
......
......@@ -329,8 +329,9 @@
left join storage_locations sl on oi.location_id = sl.id
<where>
oi.is_used = 1 and o.is_used = 1
<if test="orderId != null and orderId != ''"> and oi.order_id like concat('%', #{orderId}, '%')</if>
<if test="materialId != null and materialId != ''"> and oi.material_id = #{materialId}</if>
<if test="materialId != null and materialId != ''"> and oi.material_id like concat('%', #{materialId}, '%')</if>
<if test="batchCode != null and batchCode != ''"> and oi.batch_code = #{batchCode}</if>
<if test="warehouseId != null and warehouseId != ''"> and oi.warehouse_id = #{warehouseId}</if>
<if test="locationId != null and locationId != ''"> and oi.location_id = #{locationId}</if>
......
......@@ -105,15 +105,15 @@
<select id="selectOutboundOrdersList" parameterType="OutboundOrders" resultMap="OutboundOrdersOutboundOrderItemsResult">
<include refid="selectOutboundOrdersVo"/>
<if test="orderId != null and orderId != ''"> and oo.order_id = #{orderId}</if>
<if test="systemNo != null and systemNo != ''"> and oo.system_no = #{systemNo}</if>
<if test="orderTypeId != null and orderTypeId != ''"> and oo.order_type_id = #{orderTypeId}</if>
<if test="orderId != null and orderId != ''"> and oo.order_id like concat('%', #{orderId}, '%')</if>
<if test="batchCode != null and batchCode != ''"> and oo.batch_code like concat('%', #{batchCode}, '%')</if>
<if test="systemNo != null and systemNo != ''"> and oo.system_no like concat('%', #{systemNo}, '%')</if>
<if test="orderTypeId != null and orderTypeId != ''"> and oo.order_type_id = {orderTypeId}</if>
<if test="orderType != null and orderType != ''"> and oo.order_type = #{orderType}</if>
<if test="batchCode != null and batchCode != ''"> and oo.batch_code = #{batchCode}</if>
<if test="batchCode != null and batchCode != ''"> and oo.batch_code like concat('%', #{batchCode}, '%')</if>
<if test="warehouseId != null and warehouseId != ''"> and oo.warehouse_id = #{warehouseId}</if>
<if test="ownerId != null and ownerId != ''"> and oo.owner_id = #{ownerId}</if>
<if test="orderStatus != null "> and oo.order_status = #{orderStatus}</if>
<!-- 新增 isImport 查询条件 -->
<if test="isImport != null "> and oo.is_import = #{isImport}</if>
<if test="startDate != null"> and oo.inbound_date &gt;= #{startDate}</if>
<if test="endDate != null"> and oo.inbound_date &lt;= #{endDate}</if>
......
......@@ -33,16 +33,15 @@
<select id="selectOwnersList" parameterType="Owners" resultMap="OwnersResult">
<include refid="selectOwnersVo"/>
where is_used = 1
<if test="ownerCode != null and ownerCode != ''"> and owner_code = #{ownerCode}</if>
<if test="ownerCode != null and ownerCode != ''"> and owner_code like concat('%', #{ownerCode}, '%')</if>
<if test="ownerName != null and ownerName != ''"> and owner_name like concat('%', #{ownerName}, '%')</if>
<!-- 新增englishName查询条件 -->
<if test="englishName != null and englishName != ''"> and english_name like concat('%', #{englishName}, '%')</if>
<if test="ownerType != null "> and owner_type = #{ownerType}</if>
<if test="contactPerson != null and contactPerson != ''"> and contact_person = #{contactPerson}</if>
<if test="contactPhone != null and contactPhone != ''"> and contact_phone = #{contactPhone}</if>
<if test="email != null and email != ''"> and email = #{email}</if>
<if test="address != null and address != ''"> and address = #{address}</if>
<if test="taxNumber != null and taxNumber != ''"> and tax_number = #{taxNumber}</if>
<if test="taxNumber != null and taxNumber != ''"> and tax_number like concat('%', #{taxNumber}, '%')</if>
<if test="bankAccount != null and bankAccount != ''"> and bank_account = #{bankAccount}</if>
<if test="isActive != null "> and is_active = #{isActive}</if>
<if test="sortNo != null "> and sort_no = #{sortNo}</if>
......
......@@ -82,11 +82,11 @@
<!-- 原有列表查询(简化:移除重复的is_used=1,条件改为and开头) -->
<select id="selectStorageLocationsList" parameterType="StorageLocations" resultMap="StorageLocationsWithWarehousesResult">
<include refid="selectStorageLocationsWithWarehousesVo"/>
<if test="locationCode != null and locationCode != ''"> and sl.location_code = #{locationCode}</if>
<if test="locationCode != null and locationCode != ''"> and sl.location_code like concat('%', #{locationCode}, '%')</if>
<if test="locationName != null and locationName != ''"> and sl.location_name like concat('%', #{locationName}, '%')</if>
<if test="warehousesCode != null and warehousesCode != ''"> and sl.warehouses_code = #{warehousesCode}</if>
<if test="locationType != null "> and sl.location_type = #{locationType}</if>
<if test="zoneCode != null and zoneCode != ''"> and sl.zone_code = #{zoneCode}</if>
<if test="zoneCode != null and zoneCode != ''"> and sl.zone_code like concat('%', #{zoneCode}, '%')</if>
<if test="rowCode != null and rowCode != ''"> and sl.row_code = #{rowCode}</if>
<if test="columnCode != null and columnCode != ''"> and sl.column_code = #{columnCode}</if>
<if test="layerCode != null and layerCode != ''"> and sl.layer_code = #{layerCode}</if>
......@@ -104,7 +104,7 @@
<if test="LocationUsage != null and LocationUsage != ''"> and sl.location_usage = #{LocationUsage}</if>
<if test="locationHandling != null and locationHandling != ''"> and sl.location_handling = #{locationHandling}</if>
<if test="turnoverDemand != null and turnoverDemand != ''"> and sl.turnover_demand = #{turnoverDemand}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area like concat('%', #{pickingArea}, '%')</if>
<if test="warehousesId != null and warehousesId != ''"> and sl.warehouses_id = #{warehousesId}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
......
......@@ -30,13 +30,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectWarehousesList" parameterType="Warehouses" resultMap="WarehousesResult">
<include refid="selectWarehousesVo"/>
where is_used=1 and id != #{localId}
<if test="warehousesCode != null and warehousesCode != ''"> and warehouses_code = #{warehousesCode}</if>
<if test="warehousesCode != null and warehousesCode != ''"> and warehouses_code like concat('%', #{warehousesCode}, '%')</if>
<if test="warehousesName != null and warehousesName != ''"> and warehouses_name like concat('%', #{warehousesName}, '%')</if>
<if test="warehouseType != null "> and warehouse_type = #{warehouseType}</if>
<if test="address != null and address != ''"> and address = #{address}</if>
<if test="area != null "> and area = #{area}</if>
<if test="capacity != null "> and capacity = #{capacity}</if>
<if test="manager != null and manager != ''"> and manager = #{manager}</if>
<if test="manager != null and manager != ''"> and manager like concat('%', #{manager}, '%')</if>
<if test="contactPhone != null and contactPhone != ''"> and contact_phone = #{contactPhone}</if>
<if test="isEnabled != null "> and is_enabled = #{isEnabled}</if>
<if test="isUsed != null "> and is_used = #{isUsed}</if>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论