Commit f7de2ca4 by yubin

导入bug修改

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