Commit 19bd4ddb by yubin

导入

parent bdfed8f5
......@@ -24,7 +24,7 @@
<!-- 右侧物料列表 -->
<pane size="84" style="overflow: auto;">
<div style="padding: 10px; display: flex; flex-direction: column;">
<!-- 查询表单 -->
<!-- 查询表单(恢复所有查询项,保留ID核心逻辑) -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px">
<el-form-item label="SAP物料号" prop="sapNo">
<el-input
......@@ -56,7 +56,7 @@
</el-form-item>
</el-form>
<!-- 物料表格 -->
<!-- 物料表格(恢复所有字段显示) -->
<el-table
ref="materialTable"
v-loading="loading"
......@@ -74,6 +74,7 @@
align="center"
/>
<el-table-column type="index" label="序号" align="center"/>
<el-table-column label="物料ID" align="center" prop="id" />
<el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="TS Code" align="center" prop="tsCode" />
......@@ -119,7 +120,7 @@ export default {
components: { TreeComponent, Splitpanes, Pane },
props: {
value: {
type: [Array, String],
type: [Array, String, Number],
default: () => []
},
multiple: {
......@@ -130,7 +131,7 @@ export default {
type: Array,
default: () => []
},
selectedMaterialCodes: {
selectedMaterialIds: { // 核心:基于ID的选中项
type: Array,
default: () => []
}
......@@ -141,11 +142,11 @@ export default {
treeProps: { children: 'children', label: 'label', value: 'sid' },
nodeKey: 'sid',
loadingTree: false,
categoryMap: {},
categoryNameToCodeMap: {},
categoryCodeToSidMap: {},
categoryMap: {}, // 恢复分类名称映射(显示用)
categoryNameToCodeMap: {}, // 恢复分类名称转编码(查询用)
categoryCodeToSidMap: {}, // 恢复分类编码转SID(树选择用)
currentNodeId: null,
queryParams: {
queryParams: { // 恢复所有查询参数(显示+查询用)
pageNum: 1,
pageSize: 10,
sapNo: null,
......@@ -169,12 +170,12 @@ export default {
immediate: true,
deep: true,
handler(val) {
if (this.selectedMaterialCodes.length === 0) {
if (this.selectedMaterialIds.length === 0) {
this.handleValueChange(val)
}
}
},
selectedMaterialCodes: {
selectedMaterialIds: {
immediate: true,
deep: true,
handler(val) {
......@@ -216,14 +217,35 @@ export default {
}
},
async created() {
// 恢复分类列表和树数据加载(显示分类名称用)
await Promise.all([this.getCategoryList(), this.getCategoryTreeData()])
this.getList()
},
methods: {
// 新增:清洗名称方法(不改动原有逻辑,仅新增)
cleanMaterialName(name) {
if (!name) return ''
return name.trim().toLowerCase().replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '')
// 恢复分类列表加载(分类名称映射)
async getCategoryList() {
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 })
if (response.rows && response.rows.length > 0) {
this.categoryMap = {}
this.categoryNameToCodeMap = {}
response.rows.forEach(item => {
if (item.isUsed !== 0 && item.isUsed !== '0') {
const code = item.categoryCode
this.categoryMap[code] = item.categoryName
if (!this.categoryNameToCodeMap[item.categoryName]) {
this.categoryNameToCodeMap[item.categoryName] = code
} else if (!Array.isArray(this.categoryNameToCodeMap[item.categoryName])) {
this.categoryNameToCodeMap[item.categoryName] = [this.categoryNameToCodeMap[item.categoryName], code]
} else {
this.categoryNameToCodeMap[item.categoryName].push(code)
}
}
})
}
} catch (error) {
console.error('获取分类列表失败:', error)
}
},
handleValueChange(val) {
if (this.isSelecting) return
......@@ -255,30 +277,6 @@ export default {
this.handleValueSync()
}
},
async getCategoryList() {
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 })
if (response.rows && response.rows.length > 0) {
this.categoryMap = {}
this.categoryNameToCodeMap = {}
response.rows.forEach(item => {
if (item.isUsed !== 0 && item.isUsed !== '0') {
const code = item.categoryCode
this.categoryMap[code] = item.categoryName
if (!this.categoryNameToCodeMap[item.categoryName]) {
this.categoryNameToCodeMap[item.categoryName] = code
} else if (!Array.isArray(this.categoryNameToCodeMap[item.categoryName])) {
this.categoryNameToCodeMap[item.categoryName] = [this.categoryNameToCodeMap[item.categoryName], code]
} else {
this.categoryNameToCodeMap[item.categoryName].push(code)
}
}
})
}
} catch (error) {
console.error('获取分类列表失败:', error)
}
},
async getCategoryTreeData() {
this.loadingTree = true
try {
......@@ -347,10 +345,10 @@ export default {
getList() {
this.loading = true
listMaterials(this.queryParams).then(response => {
// 恢复所有字段映射(显示用)
this.materialsList = (response.rows || []).filter(item => item.isUsed !== 0 && item.isUsed !== '0').map(item => ({
...item,
displayCategory: this.categoryMap[item.categoryCode] || `${item.categoryCode}(未匹配分类)`,
cleanName: this.cleanMaterialName(item.materialName) // 新增:预处理清洗名称
displayCategory: this.categoryMap[item.categoryCode] || `${item.categoryCode}(未匹配分类)`
}))
this.total = response.total || 0
this.$nextTick(() => {
......@@ -365,6 +363,7 @@ export default {
})
},
handleQuery() {
// 恢复分类名称查询逻辑
const inputName = this.queryParams.categoryNameInput
if (inputName) {
const matchedCode = this.categoryNameToCodeMap[inputName]
......@@ -383,6 +382,7 @@ export default {
this.getList()
},
resetQuery() {
// 恢复所有查询参数重置
this.queryParams = {
pageNum: 1,
pageSize: 10,
......@@ -400,6 +400,7 @@ export default {
this.clearSelection()
this.getList()
},
// 核心:基于 ID 的选择事件(保留所有字段返回)
handleSelectionChange(selection) {
if (this.isSelecting || !this.$refs.materialTable) return
......@@ -420,22 +421,29 @@ export default {
this.selectedRows = selection
}
// 返回数据保留所有字段,但核心标识为id
const selectedIds = this.selectedRows.map(row => row.id)
const selectedData = this.selectedRows.map(item => ({
id: item.id,
sapNo: item.sapNo,
materialName: item.materialName,
categoryId: item.categoryCode || ''
tsCode: item.tsCode,
categoryCode: item.categoryCode,
categoryName: this.categoryMap[item.categoryCode] || item.categoryCode,
specification: item.specification,
materialUnit: item.materialUnit,
isBatchManaged: item.isBatchManaged
}))
this.$emit('selection-change', {
materialCodes: selectedIds,
materialIds: selectedIds, // 核心:返回ID数组
materials: selectedData, // 保留所有字段数据
names: selectedData.map(item => item.materialName),
categoryIds: selectedData.map(item => item.categoryId)
categoryIds: selectedData.map(item => item.categoryCode)
})
if (this.multiple) {
this.$emit('input', selectedIds)
this.$emit('input', selectedIds) // v-model绑定ID
this.$emit('change', selectedData)
} else {
const singleId = selectedIds.length > 0 ? selectedIds[0] : ''
......@@ -447,6 +455,7 @@ export default {
this.isSelecting = false
}
},
// 单选模式下的选择事件(纯 ID 逻辑,保留字段返回)
handleTableSelect(selection, row) {
if (this.isSelecting || this.multiple) return
......@@ -458,10 +467,23 @@ export default {
this.$refs.materialTable.toggleRowSelection(row, true)
this.singleSelectedId = row.id
this.selectedRows = [row]
// 返回完整字段数据
const selectedData = {
id: row.id,
sapNo: row.sapNo,
materialName: row.materialName,
tsCode: row.tsCode,
categoryCode: row.categoryCode,
categoryName: this.categoryMap[row.categoryCode] || row.categoryCode,
specification: row.specification,
materialUnit: row.materialUnit,
isBatchManaged: row.isBatchManaged
}
this.$emit('input', row.id)
this.$emit('change', { id: row.id, sapNo: row.sapNo, materialName: row.materialName })
this.$emit('change', selectedData)
this.$emit('selection-change', {
materialCodes: [row.id],
materialIds: [row.id],
materials: [selectedData],
names: [row.materialName],
categoryIds: [row.categoryCode || '']
})
......@@ -471,7 +493,8 @@ export default {
this.$emit('input', '')
this.$emit('change', null)
this.$emit('selection-change', {
materialCodes: [],
materialIds: [],
materials: [],
names: [],
categoryIds: []
})
......@@ -480,6 +503,7 @@ export default {
this.isSelecting = false
}
},
// 行点击事件(纯 ID 逻辑,保留字段返回)
handleRowClick(row) {
if (this.isSelecting || !this.$refs.materialTable) return
......@@ -493,10 +517,23 @@ export default {
this.$refs.materialTable.toggleRowSelection(row, true)
this.singleSelectedId = row.id
this.selectedRows = [row]
// 返回完整字段数据
const selectedData = {
id: row.id,
sapNo: row.sapNo,
materialName: row.materialName,
tsCode: row.tsCode,
categoryCode: row.categoryCode,
categoryName: this.categoryMap[row.categoryCode] || row.categoryCode,
specification: row.specification,
materialUnit: row.materialUnit,
isBatchManaged: row.isBatchManaged
}
this.$emit('input', row.id)
this.$emit('change', { id: row.id, sapNo: row.sapNo, materialName: row.materialName })
this.$emit('change', selectedData)
this.$emit('selection-change', {
materialCodes: [row.id],
materialIds: [row.id],
materials: [selectedData],
names: [row.materialName],
categoryIds: [row.categoryCode || '']
})
......@@ -506,7 +543,8 @@ export default {
this.$emit('input', '')
this.$emit('change', null)
this.$emit('selection-change', {
materialCodes: [],
materialIds: [],
materials: [],
names: [],
categoryIds: []
})
......@@ -518,6 +556,7 @@ export default {
this.isSelecting = false
}
},
// 清空选择(纯 ID 逻辑)
clearSelection() {
if (this.isSelecting || !this.$refs.materialTable) return
......@@ -529,7 +568,8 @@ export default {
this.$emit('input', this.multiple ? [] : '')
this.$emit('change', this.multiple ? [] : null)
this.$emit('selection-change', {
materialCodes: [],
materialIds: [],
materials: [],
names: [],
categoryIds: []
})
......@@ -537,27 +577,27 @@ export default {
this.isSelecting = false
}
},
// 核心修改:反显逻辑改为匹配物料名称
// 核心:基于 ID 的反显逻辑(保留所有字段显示)
handleValueSync(isRetry = false) {
if (this.loading || this.isSelecting || !this.$refs.materialTable) return
if (isRetry) this.isRetrySync = true
const val = this.selectedMaterialCodes.length ? this.selectedMaterialCodes : this.value
// 优先使用 selectedMaterialIds,其次是 value
const val = this.selectedMaterialIds.length ? this.selectedMaterialIds : this.value
if (!val || (Array.isArray(val) && !val.length)) {
this.clearSelection()
this.isRetrySync = false
return
}
// 处理名称格式:转数组+清洗
const targetNames = this.multiple
? Array.isArray(val) ? val : [val]
: [Array.isArray(val) ? val[0] : val]
const targetCleanNames = targetNames.map(name => this.cleanMaterialName(name)).filter(Boolean)
const targetRawNames = targetNames.filter(Boolean)
// 统一处理 ID 格式(兼容字符串/数字)
const targetIds = this.multiple
? Array.isArray(val) ? val.map(id => String(id)) : [String(val)]
: [String(Array.isArray(val) ? val[0] : val)]
const validTargetIds = targetIds.filter(id => id && id !== 'undefined' && id !== 'null')
if (!targetCleanNames.length && !targetRawNames.length) {
if (!validTargetIds.length) {
this.clearSelection()
this.isRetrySync = false
return
......@@ -568,36 +608,36 @@ export default {
this.$refs.materialTable.clearSelection()
let matchedCount = 0
// 匹配物料名称(精准/清洗后
// 基于 ID 精准匹配反显(保留所有字段
this.materialsList.forEach(row => {
const rowRawName = row.materialName
const rowCleanName = row.cleanName || this.cleanMaterialName(rowRawName)
const isMatched = targetRawNames.includes(rowRawName) || targetCleanNames.includes(rowCleanName)
if (isMatched) {
const rowId = String(row.id)
if (validTargetIds.includes(rowId)) {
this.$refs.materialTable.toggleRowSelection(row, true)
matchedCount++
}
})
// 刷新选中行
this.selectedRows = this.materialsList.filter(row => {
const rowRawName = row.materialName
const rowCleanName = row.cleanName || this.cleanMaterialName(rowRawName)
return targetRawNames.includes(rowRawName) || targetCleanNames.includes(rowCleanName)
})
// 更新选中行
this.selectedRows = this.materialsList.filter(row =>
validTargetIds.includes(String(row.id))
)
this.singleSelectedId = this.multiple ? null : (this.selectedRows[0]?.id || null)
// 未匹配到的处理
if (matchedCount === 0 && !isRetry) {
this.$emit('selection-change', { materialCodes: [], names: [], categoryIds: [] })
this.$emit('selection-change', {
materialIds: [],
materials: [],
names: [],
categoryIds: []
})
this.$emit('input', this.multiple ? [] : '')
}
if (matchedCount === 0 && isRetry) {
console.warn('反显重试仍未匹配到数据', {
targetNames: targetRawNames,
targetCleanNames: targetCleanNames,
listNames: this.materialsList.map(r => r.materialName)
console.warn('反显重试仍未匹配到ID', {
targetIds: validTargetIds,
listIds: this.materialsList.map(r => String(r.id))
})
}
} catch (e) {
......@@ -607,7 +647,8 @@ export default {
this.isRetrySync = false
}
},
setSelectedCodes(codes) {
// 外部设置选中 ID 的方法
setSelectedIds(ids) {
if (this.isSelecting) return
this.isSelecting = true
......@@ -617,7 +658,7 @@ export default {
this.getList().then(() => {
this.$nextTick(() => {
this.$props.selectedMaterialCodes = codes
this.$props.selectedMaterialIds = ids
this.handleValueSync(true)
})
})
......@@ -625,13 +666,35 @@ export default {
this.isSelecting = false
}
},
// 获取选中物料(返回完整字段,核心为ID)
getSelectedMaterials() {
if (this.multiple) {
return this.selectedRows.map(row => ({ id: row.id, sapNo: row.sapNo, materialName: row.materialName }))
return this.selectedRows.map(row => ({
id: row.id,
sapNo: row.sapNo,
materialName: row.materialName,
tsCode: row.tsCode,
categoryCode: row.categoryCode,
categoryName: this.categoryMap[row.categoryCode] || row.categoryCode,
specification: row.specification,
materialUnit: row.materialUnit,
isBatchManaged: row.isBatchManaged
}))
} else {
return this.selectedRows[0] ? { id: this.selectedRows[0].id, sapNo: this.selectedRows[0].sapNo, materialName: this.selectedRows[0].materialName } : null
return this.selectedRows[0] ? {
id: this.selectedRows[0].id,
sapNo: this.selectedRows[0].sapNo,
materialName: this.selectedRows[0].materialName,
tsCode: this.selectedRows[0].tsCode,
categoryCode: this.selectedRows[0].categoryCode,
categoryName: this.categoryMap[this.selectedRows[0].categoryCode] || this.selectedRows[0].categoryCode,
specification: this.selectedRows[0].specification,
materialUnit: this.selectedRows[0].materialUnit,
isBatchManaged: this.selectedRows[0].isBatchManaged
} : null
}
},
// 单选模式下设置选中 ID
setSingleSelection(id) {
if (this.isSelecting || this.multiple) return
......@@ -644,10 +707,23 @@ export default {
if (targetRow) {
this.$refs.materialTable.toggleRowSelection(targetRow, true)
this.selectedRows = [targetRow]
// 返回完整字段数据
const selectedData = {
id: targetRow.id,
sapNo: targetRow.sapNo,
materialName: targetRow.materialName,
tsCode: targetRow.tsCode,
categoryCode: targetRow.categoryCode,
categoryName: this.categoryMap[targetRow.categoryCode] || targetRow.categoryCode,
specification: targetRow.specification,
materialUnit: targetRow.materialUnit,
isBatchManaged: targetRow.isBatchManaged
}
this.$emit('input', id)
this.$emit('change', { id: targetRow.id, sapNo: targetRow.sapNo, materialName: targetRow.materialName })
this.$emit('change', selectedData)
this.$emit('selection-change', {
materialCodes: [id],
materialIds: [id],
materials: [selectedData],
names: [targetRow.materialName],
categoryIds: [targetRow.categoryCode || '']
})
......@@ -655,7 +731,8 @@ export default {
this.$emit('input', '')
this.$emit('change', null)
this.$emit('selection-change', {
materialCodes: [],
materialIds: [],
materials: [],
names: [],
categoryIds: []
})
......
......@@ -113,6 +113,53 @@
/>
</el-select>
</el-form-item>
<!-- 新增查询字段 -->
<el-form-item label="库位使用" prop="locationUsage">
<el-select
v-model="queryParams.locationUsage"
placeholder="请选择库位使用"
clearable
style="width: 100%;"
>
<el-option
v-for="item in dict.type.location_usage"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="允许混放产品" prop="allowMixedProducts">
<el-select
v-model="queryParams.allowMixedProducts"
placeholder="请选择是否允许混放产品"
clearable
style="width: 100%;"
>
<el-option
v-for="item in dict.type.yorn"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="上架区" prop="zoneCode">
<el-input
v-model="queryParams.zoneCode"
placeholder="请输入上架区"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="拣货区" prop="pickingArea">
<el-input
v-model="queryParams.pickingArea"
placeholder="请输入拣货区"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</page-wrapper-search>
<div class="table-container">
......@@ -141,6 +188,39 @@
<div><strong>层:</strong>{{ scope.row.layerCode || '-' }}</div>
</el-col>
</el-row>
<!-- 新增展开字段 -->
<el-row :gutter="20" style="margin: 10px 0;">
<el-col :span="6">
<div><strong>上架顺序:</strong>{{ scope.row.putawayOrder || '-' }}</div>
</el-col>
<el-col :span="6">
<div><strong>拣货顺序:</strong>{{ scope.row.pickingOrder || '-' }}</div>
</el-col>
<el-col :span="6">
<div><strong>库位处理:</strong>{{ scope.row.locationHandling || '-' }}</div>
</el-col>
<el-col :span="6">
<div><strong>周转需求:</strong>{{ scope.row.turnoverDemand || '-' }}</div>
</el-col>
</el-row>
<el-row :gutter="20" style="margin: 10px 0;">
<el-col :span="6">
<div><strong>库位使用:</strong>
<dict-tag :options="dict.type.location_usage" :value="scope.row.locationUsage"/>
</div>
</el-col>
<el-col :span="6">
<div><strong>允许混放产品:</strong>
<dict-tag :options="dict.type.yorn" :value="scope.row.allowMixedProducts"/>
</div>
</el-col>
<el-col :span="6">
<div><strong>允许混放批次:</strong>{{ scope.row.allowMixedBatches || '-' }}</div>
</el-col>
<el-col :span="6">
<div><strong>拣货区:</strong>{{ scope.row.pickingArea || '-' }}</div>
</el-col>
</el-row>
<el-row :gutter="20" style="margin: 10px 0;">
<el-col :span="24">
<div><strong>允许存放物料名称:</strong>{{ scope.row.materialNames || '-' }}</div>
......@@ -161,6 +241,23 @@
<dict-tag :options="dict.type.location_type" :value="scope.row.locationType"/>
</template>
</el-table-column>
<!-- 新增表格列 -->
<el-table-column label="库位使用" align="center" prop="locationUsage" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.location_usage" :value="scope.row.locationUsage"/>
</template>
</el-table-column>
<el-table-column label="上架区" align="center" prop="zoneCode" width="100" />
<el-table-column label="拣货区" align="center" prop="pickingArea" width="100" />
<el-table-column label="允许混放产品" align="center" prop="allowMixedProducts" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.yorn" :value="scope.row.allowMixedProducts"/>
</template>
</el-table-column>
<el-table-column label="允许混放批次" align="center" prop="allowMixedBatches" width="120" />
<el-table-column label="上架顺序" align="center" prop="putawayOrder" width="100" />
<el-table-column label="拣货顺序" align="center" prop="pickingOrder" width="100" />
<el-table-column label="库位容量(千克)" align="center" prop="capacity" width="120" />
<el-table-column label="体积容量(立方米)" align="center" prop="volumeCapacity" width="120" />
<el-table-column label="允许存放的危险等级" align="center" prop="allowedHazardLevels" width="140" />
......@@ -243,7 +340,7 @@
</div>
<!-- 添加或修改库位对话框 -->
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
......@@ -299,6 +396,73 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="库位使用" prop="locationUsage">
<el-select v-model="form.locationUsage" placeholder="请选择库位使用" style="width: 100%;">
<el-option
v-for="item in dict.type.location_usage"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="上架区" prop="zoneCode">
<el-input v-model="form.zoneCode" placeholder="请输入上架区" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="拣货区" prop="pickingArea">
<el-input v-model="form.pickingArea" placeholder="请输入拣货区" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="上架顺序" prop="putawayOrder">
<el-input v-model="form.putawayOrder" placeholder="请输入上架顺序" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="拣货顺序" prop="pickingOrder">
<el-input v-model="form.pickingOrder" placeholder="请输入拣货顺序" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="允许混放产品" prop="allowMixedProducts">
<el-select v-model="form.allowMixedProducts" placeholder="请选择是否允许混放产品" style="width: 100%;">
<el-option
v-for="item in dict.type.yorn"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="允许混放批次" prop="allowMixedBatches">
<el-input v-model="form.allowMixedBatches" placeholder="请输入允许混放批次" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="库位处理" prop="locationHandling">
<el-input v-model="form.locationHandling" placeholder="请输入库位处理" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="周转需求" prop="turnoverDemand">
<el-input v-model="form.turnoverDemand" placeholder="请输入周转需求" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
......@@ -431,7 +595,7 @@
</div>
</el-dialog>
<!-- 导入组件 -->
<!-- 导入组件 - 集成货主页面的导入功能 -->
<import-excel
ref="import"
title="库位导入"
......@@ -440,6 +604,8 @@
template-name="locations_importTemplate"
@success="getList"
/>
<!-- 仓库选择器组件 -->
<WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
......@@ -458,7 +624,8 @@ import { listMaterials } from "@/api/inventory/materials"
export default {
name: "Locations",
components: { materialsSeletor, WarehouseSelector, ImportExcel },
dicts: ['sys_normal_disable', 'location_type'],
// 新增字典类型
dicts: ['sys_normal_disable', 'location_type', 'location_usage', 'yorn'],
data() {
return {
loading: true,
......@@ -482,6 +649,12 @@ export default {
sys_normal_disable: [
{ label: "启用", value: "1" },
{ label: "禁用", value: "0" }
],
// 新增字典默认值(实际会从后端加载)
location_usage: [],
yorn: [
{ label: "是", value: "Y" },
{ label: "否", value: "N" }
]
}
},
......@@ -493,7 +666,12 @@ export default {
locationName: null,
warehouseId: null, // 前端保持warehouseId,内部映射后端的warehousesId
locationType: null,
layerCode: null
layerCode: null,
// 新增查询参数
locationUsage: null,
allowMixedProducts: null,
zoneCode: null,
pickingArea: null
},
form: {
......@@ -517,7 +695,16 @@ export default {
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
sortNo: 0
sortNo: 0,
// 新增表单字段
putawayOrder: null,
pickingOrder: null,
locationUsage: null,
locationHandling: null,
turnoverDemand: null,
pickingArea: null,
allowMixedProducts: null,
allowMixedBatches: null
},
rules: {
......@@ -535,6 +722,13 @@ export default {
locationType: [
{ required: true, message: '库位类型不能为空', trigger: 'change' }
],
// 新增表单验证规则
locationUsage: [
{ required: true, message: '库位使用不能为空', trigger: 'change' }
],
allowMixedProducts: [
{ required: true, message: '允许混放产品不能为空', trigger: 'change' }
],
isEnabled: [
{ required: true, message: '应用状态不能为空', trigger: 'change' }
]
......@@ -712,7 +906,12 @@ export default {
locationName: null,
warehouseId: null,
locationType: null,
layerCode: null
layerCode: null,
// 重置新增的查询参数
locationUsage: null,
allowMixedProducts: null,
zoneCode: null,
pickingArea: null
}
this.queryWarehouseName = ''
this.getList()
......@@ -901,7 +1100,7 @@ export default {
this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
},
// 导入库位
// 导入库位 - 集成货主页面的导入逻辑
handleImport() {
this.$refs.import.show()
},
......@@ -929,7 +1128,16 @@ export default {
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
sortNo: 0
sortNo: 0,
// 重置新增的表单字段
putawayOrder: null,
pickingOrder: null,
locationUsage: null,
locationHandling: null,
turnoverDemand: null,
pickingArea: null,
allowMixedProducts: null,
allowMixedBatches: null
}
this.tempSelectedMaterials = {
materialCodes: [],
......
......@@ -13,8 +13,8 @@
<el-col :span="12">
<el-form-item label="货物ID" prop="materialId">
<el-input
v-model="form.materialId"
placeholder="请选择或输入货物ID"
v-model="form.materialName"
placeholder="请选择物料"
readonly
@click.native="!isMaterialLocked && (openMaterialSelector = true)"
style="cursor: pointer"
......@@ -29,34 +29,38 @@
></el-button>
</template>
</el-input>
<el-dialog
v-if="!isMaterialLocked"
title="选择物料"
:visible.sync="openMaterialSelector"
width="90%"
append-to-body
:close-on-click-modal="false"
:close-on-press-escape="false"
:modal="true"
:modal-append-to-body="true"
>
<div style="height: 70vh; overflow: auto; padding: 0 10px;">
<MaterialSelector
ref="materialsSeletor"
@selection-change="handleMaterialSelectionChange"
:selected-material-codes="form.materialUuids ? [form.materialUuids] : []"
:multiple="false"
/>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click.native="openMaterialSelector = false">取消</el-button>
<el-button type="primary" @click.native="confirmMaterialSelect">确认选择</el-button>
</div>
</el-dialog>
<el-input v-model="form.materialId" type="hidden" />
</el-form-item>
</el-col>
</el-row>
<!-- 选择物料的弹窗 -->
<el-dialog
v-if="!isMaterialLocked"
title="选择物料"
:visible.sync="openMaterialSelector"
width="90%"
append-to-body
:close-on-click-modal="false"
:close-on-press-escape="false"
:modal="true"
:modal-append-to-body="true"
>
<div style="height: 70vh; overflow: auto; padding: 0 10px;">
<MaterialSelector
ref="materialsSeletor"
@selection-change="handleMaterialSelectionChange"
:selected-material-codes="form.materialUuids ? [form.materialUuids] : []"
:multiple="false"
/>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click.native="openMaterialSelector = false">取消</el-button>
<el-button type="primary" @click.native="confirmMaterialSelect">确认选择</el-button>
</div>
</el-dialog>
<!-- 库存信息列表 -->
<el-row v-if="form.materialId && form.materialId.trim()" style="margin: 10px 0;">
<el-col :span="24">
<div style="margin-bottom: 8px; font-weight: 600; color: #1989fa;">
......@@ -74,10 +78,11 @@
@row-click="handleRowClick"
:row-key="item => item.inventoryId"
>
<el-table-column prop="materialId" label="货物ID" width="150" />
<el-table-column prop="materialName" label="物料名称" width="180" />
<el-table-column prop="batchId" label="批次ID" width="150" />
<el-table-column prop="outboundOrderId" label="出库单号" width="150" />
<!-- <el-table-column prop="warehouseId" label="仓库ID" width="120" /> -->
<el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column prop="locationId" label="库位ID" width="140" />
<el-table-column
prop="inventoryType"
......@@ -110,6 +115,7 @@
</el-table-column>
</el-table>
<!-- 库存明细信息 -->
<div
v-if="currentSelectedRow"
style="margin-top: 10px; padding: 10px; border: 1px solid #e6e6e6; border-radius: 4px;"
......@@ -131,15 +137,15 @@
</el-col>
<el-col :span="8">
<el-form-item label="标签颜色" prop="labelColor">
<el-select
v-model="currentSelectedRow.labelColor"
<el-select
v-model="currentSelectedRow.labelColor"
placeholder="请选择标签颜色"
style="width: 100%;"
>
<el-option
v-for="color in dict.type.label_color"
:key="color.value"
:label="color.label"
<el-option
v-for="color in dict.type.label_color"
:key="color.value"
:label="color.label"
:value="color.value"
/>
</el-select>
......@@ -191,17 +197,6 @@
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 10px;">
<!-- <el-col :span="8">
<el-form-item label="发货时间" prop="shippedAt">
<el-date-picker
v-model="currentSelectedRow.shippedAt"
type="date"
placeholder="选择发货时间"
style="width: 100%;"
@input="syncDetails(false)"
/>
</el-form-item>
</el-col> -->
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input
......@@ -218,6 +213,7 @@
</el-col>
</el-row>
<!-- 已生成明细项 -->
<el-row v-if="details.length > 0" style="margin: 10px 0;">
<el-col :span="24">
<div style="margin-bottom: 8px; font-weight: 600; color: #1989fa;">
......@@ -230,23 +226,23 @@
max-height="200"
:row-key="item => item.inventoryId"
>
<!-- <el-table-column prop="inventoryId" label="库存ID" width="100" /> -->
<el-table-column prop="batchId" label="批次ID" />
<!-- <el-table-column prop="warehouseId" label="仓库ID" /> -->
<el-table-column prop="locationId" label="库位ID" />
<el-table-column prop="plannedQuantity" label="计划数量" />
<el-table-column prop="actualQuantity" label="实际数量" />
<el-table-column prop="unitPrice" label="单价" />
<el-table-column prop="divisor" label="约数" />
<el-table-column prop="labelColor" label="标签颜色">
<el-table-column prop="materialName" label="物料名称" width="180" />
<el-table-column prop="batchId" label="批次ID" width="150" />
<el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column prop="locationId" label="库位ID" width="140" />
<el-table-column prop="plannedQuantity" label="计划数量" width="100" />
<el-table-column prop="actualQuantity" label="实际数量" width="100" />
<el-table-column prop="unitPrice" label="单价" width="100" />
<el-table-column prop="divisor" label="约数" width="80" />
<el-table-column prop="labelColor" label="标签颜色" width="100">
<template slot-scope="scope">
<dict-tag v-if="dict.type.label_color" :options="dict.type.label_color" :value="scope.row.labelColor"/>
</template>
</el-table-column>
<el-table-column prop="voucherNumber" label="凭证号" />
<el-table-column prop="shippedBy" label="发货方" />
<!-- <el-table-column prop="shippedAt" label="发货时间" /> -->
<el-table-column prop="remark" label="备注" />
<el-table-column prop="voucherNumber" label="凭证号" width="120" />
<el-table-column prop="shippedBy" label="发货方" width="120" />
<el-table-column prop="remark" label="备注" width="150" />
<el-table-column label="操作" width="80">
<template slot-scope="scope">
<el-button
......@@ -260,6 +256,8 @@
</el-col>
</el-row>
</el-form>
<!-- 弹窗底部按钮 -->
<div slot="footer" class="dialog-footer">
<el-button @click.native="handleClose">取消</el-button>
<el-button type="primary" @click.native="handleSubmit">生成明细</el-button>
......@@ -314,7 +312,7 @@ export default {
},
ordersId: {
type: String,
default:""
default: ""
}
},
data() {
......@@ -322,6 +320,7 @@ export default {
form: {
materialUuids: '',
materialId: '',
materialName: '',
itemStatus: 1,
outboundOrderId: ''
},
......@@ -358,17 +357,16 @@ export default {
this.form = {
...this.$options.data().form,
...this.initForm,
materialName: this.initForm.materialName || '',
outboundOrderId: this.outboundOrderId || this.initForm.outboundOrderId || ''
};
this.selectedMaterialId = this.form.materialId || '';
this.selectedMaterialInfo = null;
this.currentSelectedRowId = null;
this.details = this.initDetails.length > 0 ? JSON.parse(JSON.stringify(this.initDetails)) : [];
// 强制等待DOM更新后再查库存,避免数据未初始化
this.$nextTick(async () => {
if (this.form.materialId && this.form.materialId.trim()) {
await this.handleMaterialIdChange();
// 二次确认:库存加载完成后手动触发回显
if (this.inventoryList.length > 0 && !this.isInitEcho) {
this.initEchoDetails();
this.isInitEcho = true;
......@@ -393,12 +391,12 @@ export default {
this.form = {
...this.$options.data().form,
...val,
materialName: val.materialName || '',
outboundOrderId: this.outboundOrderId || val.outboundOrderId || ''
};
const oldMaterialId = this.selectedMaterialId;
this.selectedMaterialId = this.form.materialId || '';
this.currentSelectedRowId = null;
// 强制等待DOM更新后再查库存
this.$nextTick(async () => {
if (this.form.materialId && this.form.materialId.trim() && this.form.materialId !== oldMaterialId) {
await this.handleMaterialIdChange();
......@@ -460,7 +458,7 @@ export default {
lock: true,
background: 'rgba(0, 0, 0, 0.7)'
});
console.log("this.form",this.form)
console.log("this.form", this.form);
const params = {
materialId: materialId,
outboundOrderId: this.ordersId
......@@ -468,20 +466,23 @@ export default {
console.log('【查询库存参数】', params);
const res = await listInventoryByMaterialId(params);
console.log('【库存接口返回】', res);
console.log('【库存接口原始行数据】', res.rows); // 打印原始行数据
console.log('【库存接口原始行数据】', res.rows);
if (res.code === 200) {
this.inventoryList = [];
(res.rows || []).forEach(item => {
console.log('【单条库存数据】', item); // 打印单条库存数据
console.log('【单条库存数据】', item);
const newRow = {
// 核心修复:优先取item.inventoryId(匹配回显字段),兼容item.id
inventoryId: item.inventoryId || item.id,
id: item.id, // 保留原id字段
inventoryId: item.id,
id: item.id,
materialId: item.materialId || materialId,
materialName: item.materialName || '',
batchId: item.batchId || '',
outboundOrderId: item.outboundOrderId || this.form.outboundOrderId,
warehouseId: item.warehouseId || '',
outboundOrderId: item.orderId || this.form.outboundOrderId,
warehouseId: item.warehousesId || '',
warehousesId: item.warehousesId || '',
warehousesName: item.warehousesName || '',
locationId: item.locationId || '',
locationName: item.locationName || '',
inventoryType: item.inventoryType || 1,
quantity: item.quantity || 0,
lockedQuantity: item.lockedQuantity || 0,
......@@ -498,6 +499,9 @@ export default {
};
this.inventoryList.push(newRow);
});
if (this.inventoryList.length > 0 && !this.form.materialName) {
this.$set(this.form, 'materialName', this.inventoryList[0].materialName || '');
}
console.log('【组装后的库存列表】', this.inventoryList);
console.log('【待回显的initDetails】', this.initDetails);
......@@ -517,64 +521,67 @@ export default {
});
}
},
initEchoDetails() {
console.log('【开始回显】inventoryList=', this.inventoryList, 'initDetails=', this.initDetails);
if (this.initDetails.length === 0 || this.inventoryList.length === 0) return;
// 1. 先清空所有库存行的临时数据(避免残留)
this.inventoryList.forEach(row => {
this.$set(row, 'actualQuantity', null);
this.$set(row, 'plannedQuantity', null);
this.$set(row, 'divisor', null);
this.$set(row, 'labelColor', '');
this.$set(row, 'unitPrice', null);
this.$set(row, 'shippedBy', '');
this.$set(row, 'voucherNumber', '');
this.$set(row, 'remark', '');
});
// 2. 遍历所有initDetails明细项,逐个匹配库存行并回显
this.initDetails.forEach(detail => {
let targetRow = null;
// 方案1:优先用inventoryId精确匹配(最可靠)
targetRow = this.inventoryList.find(row => row.inventoryId === detail.inventoryId);
// 方案2:兜底用batchId+warehouseId+locationId组合匹配
if (!targetRow) {
targetRow = this.inventoryList.find(row =>
row.batchId === detail.batchId &&
row.warehouseId === detail.warehouseId &&
row.locationId === detail.locationId
);
}
initEchoDetails() {
console.log('【开始回显】inventoryList=', this.inventoryList, 'initDetails=', this.initDetails);
if (this.initDetails.length === 0 || this.inventoryList.length === 0) return;
// 方案3:终极兜底(如果允许“无匹配则不回显”,可去掉这一步)
if (!targetRow) {
console.warn('【匹配失败】明细无对应库存行,detail.inventoryId=', detail.inventoryId);
return; // 跳过当前明细的回显
}
this.inventoryList.forEach(row => {
this.$set(row, 'actualQuantity', null);
this.$set(row, 'plannedQuantity', null);
this.$set(row, 'divisor', null);
this.$set(row, 'labelColor', '');
this.$set(row, 'unitPrice', null);
this.$set(row, 'shippedBy', '');
this.$set(row, 'voucherNumber', '');
this.$set(row, 'remark', '');
});
this.initDetails.forEach(detail => {
let targetRow = null;
targetRow = this.inventoryList.find(row => row.inventoryId === detail.inventoryId);
if (!targetRow) {
targetRow = this.inventoryList.find(row =>
row.batchId === detail.batchId &&
row.warehousesId === detail.warehousesId &&
row.locationId === detail.locationId
);
}
if (!targetRow) {
targetRow = this.inventoryList.find(row =>
row.batchId === detail.batchId &&
row.materialId === detail.materialId
);
}
if (!targetRow) {
console.warn('【匹配失败】明细无对应库存行,detail.inventoryId=', detail.inventoryId);
return;
}
this.$set(targetRow, 'actualQuantity', detail.actualQuantity ?? null);
this.$set(targetRow, 'plannedQuantity', detail.plannedQuantity ?? null);
this.$set(targetRow, 'divisor', detail.divisor ?? null);
this.$set(targetRow, 'labelColor', detail.labelColor ?? '');
this.$set(targetRow, 'unitPrice', detail.unitPrice ?? null);
this.$set(targetRow, 'shippedBy', detail.shippedBy ?? '');
this.$set(targetRow, 'voucherNumber', detail.voucherNumber ?? '');
this.$set(targetRow, 'remark', detail.remark ?? '');
if (detail.warehousesName) this.$set(targetRow, 'warehousesName', detail.warehousesName);
if (detail.locationName) this.$set(targetRow, 'locationName', detail.locationName);
if (detail.materialName) this.$set(targetRow, 'materialName', detail.materialName);
});
// 3. 给匹配到的库存行赋值回显数据
this.$set(targetRow, 'actualQuantity', detail.actualQuantity ?? null);
this.$set(targetRow, 'plannedQuantity', detail.plannedQuantity ?? null);
this.$set(targetRow, 'divisor', detail.divisor ?? null);
this.$set(targetRow, 'labelColor', detail.labelColor ?? '');
this.$set(targetRow, 'unitPrice', detail.unitPrice ?? null);
this.$set(targetRow, 'shippedBy', detail.shippedBy ?? '');
this.$set(targetRow, 'voucherNumber', detail.voucherNumber ?? '');
this.$set(targetRow, 'remark', detail.remark ?? '');
});
// 4. 同步明细数据(保持页面显示一致)
this.syncDetails(false);
console.log('【回显完成】inventoryList=', this.inventoryList);
},
this.syncDetails(false);
console.log('【回显完成】inventoryList=', this.inventoryList);
},
handleRowClick(row) {
if (!row) return;
this.currentSelectedRowId = row.inventoryId;
},
handleRowActualQtyInput(row) {
if (isNaN(row.actualQuantity) || row.actualQuantity === '') {
if (isNaN(row.actualQuantity) || row.actualQuantity === '' || row.actualQuantity === null) {
this.$set(row, 'actualQuantity', null);
return;
}
......@@ -588,7 +595,7 @@ export default {
}
},
handleRowPlannedQtyInput(row) {
if (isNaN(row.plannedQuantity) || row.plannedQuantity === '') {
if (isNaN(row.plannedQuantity) || row.plannedQuantity === '' || row.plannedQuantity === null) {
this.$set(row, 'plannedQuantity', null);
return;
}
......@@ -613,6 +620,9 @@ export default {
row.actualQuantity >= 1 &&
row.actualQuantity <= availableQty &&
row.plannedQuantity !== null &&
row.plannedQuantity !== undefined &&
row.plannedQuantity >= 1 &&
row.plannedQuantity <= availableQty &&
row.divisor !== null &&
row.labelColor !== '' &&
row.voucherNumber !== '' &&
......@@ -626,7 +636,6 @@ export default {
row.labelColor !== '' ||
row.unitPrice !== null ||
row.shippedBy !== '' ||
// row.shippedAt !== '' ||
row.voucherNumber !== '' ||
row.remark !== '';
});
......@@ -636,9 +645,13 @@ export default {
const newDetail = {
inventoryId: row.inventoryId,
materialId: row.materialId || this.form.materialId,
materialName: row.materialName || this.form.materialName || '',
batchId: row.batchId || row.batchCode || '',
warehouseId: row.warehouseId || '',
warehouseId: row.warehouseId,
warehousesId: row.warehousesId || '',
warehousesName: row.warehousesName || '',
locationId: row.locationId || '',
locationName: row.locationName || '',
outboundOrderId: this.form.outboundOrderId || '',
plannedQuantity: row.plannedQuantity,
actualQuantity: row.actualQuantity,
......@@ -646,7 +659,6 @@ export default {
labelColor: row.labelColor,
unitPrice: row.unitPrice,
shippedBy: row.shippedBy,
// shippedAt: row.shippedAt,
voucherNumber: row.voucherNumber,
remark: row.remark
};
......@@ -663,7 +675,6 @@ export default {
this.$set(inventoryRow, 'labelColor', '');
this.$set(inventoryRow, 'unitPrice', null);
this.$set(inventoryRow, 'shippedBy', '');
// this.$set(inventoryRow, 'shippedAt', '');
this.$set(inventoryRow, 'voucherNumber', '');
this.$set(inventoryRow, 'remark', '');
if (this.currentSelectedRowId === row.inventoryId) {
......@@ -693,6 +704,7 @@ export default {
const submitDetails = this.details.map(detail => ({
...detail,
materialName: this.form.materialName || detail.materialName,
outboundOrderId: this.form.outboundOrderId || detail.outboundOrderId,
materialId: this.form.materialId || detail.materialId
}));
......@@ -720,34 +732,73 @@ export default {
});
this.$emit('update:open', false);
},
handleMaterialSelectionChange() {
const selectedData = this.$refs.materialsSeletor?.getSelectedMaterials?.() || this.$refs.materialsSeletor?.selectedList || [];
if (selectedData) {
this.selectedMaterialInfo = selectedData;
this.selectedMaterialId = this.selectedMaterialInfo.sapNo || this.selectedMaterialInfo.materialId || '';
console.log("选中的SAP物料号:", this.selectedMaterialId);
// 修复:接收selection-change事件参数,兼容多种字段名
handleMaterialSelectionChange(selectedData) {
console.log("【物料选择事件触发】选中数据:", selectedData);
// 兼容数组格式(multiple=false时可能返回对象,需转为数组)
const selectList = Array.isArray(selectedData) ? selectedData : selectedData ? [selectedData] : [];
if (selectList.length > 0) {
this.selectedMaterialInfo = selectList[0];
// 关键:兼容常见的物料ID字段名(id/materialId/uuid)
this.selectedMaterialId = this.selectedMaterialInfo.id || this.selectedMaterialInfo.materialId || this.selectedMaterialInfo.uuid || '';
// 兼容常见的物料名称字段名(materialName/name)
this.$set(this.form, 'materialName', this.selectedMaterialInfo.materialName || this.selectedMaterialInfo.name || '');
console.log("【物料选择成功】ID:", this.selectedMaterialId, "名称:", this.form.materialName);
} else {
this.selectedMaterialInfo = null;
this.selectedMaterialId = '';
this.$set(this.form, 'materialName', '');
console.log("【物料选择清空】");
}
},
// 修复:增强校验逻辑,增加组件存在性检查和异步同步
confirmMaterialSelect() {
this.handleMaterialSelectionChange();
if (!this.selectedMaterialId) {
this.$message.warning('请选择物料后再确认');
// 1. 检查选择器组件是否存在
if (!this.$refs.materialsSeletor) {
this.$message.error('物料选择器组件加载失败,请重试');
return;
}
this.$set(this.form, 'materialId', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
this.$set(this.form, 'materialUuids', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
this.openMaterialSelector = false;
this.handleMaterialIdChange();
// 2. 异步等待组件数据同步(避免取值过早)
this.$nextTick(() => {
if (this.$refs.detailForm) {
this.$refs.detailForm.validateField('materialId');
// 3. 强制触发选中数据同步
const selector = this.$refs.materialsSeletor;
let selectedData = [];
// 兼容组件的多种取值方式
if (selector.getSelectedMaterials) {
selectedData = selector.getSelectedMaterials();
} else if (selector.selectedList) {
selectedData = selector.selectedList;
} else if (selector.value) {
selectedData = selector.value;
}
// 触发数据同步(覆盖事件未触发的场景)
this.handleMaterialSelectionChange(selectedData);
// 4. 增强空值校验
if (!this.selectedMaterialInfo || !this.selectedMaterialId) {
this.$message.warning('请选择物料后再确认');
return;
}
// 5. 容错处理:确保物料ID有效
const materialId = this.selectedMaterialInfo.id || this.selectedMaterialInfo.materialId || this.selectedMaterialInfo.uuid || '';
if (!materialId) {
this.$message.error('选中的物料缺少有效ID,请重新选择');
return;
}
// 6. 赋值并关闭弹窗
this.$set(this.form, 'materialId', materialId);
this.$set(this.form, 'materialUuids', materialId);
this.openMaterialSelector = false;
// 7. 查询库存并校验字段
this.handleMaterialIdChange();
this.$nextTick(() => {
this.$refs.detailForm?.validateField('materialId');
});
});
}
},
......
......@@ -20,6 +20,14 @@
@click="handleUpdate"
v-hasPermi="['inventory:orders:edit']"
>修改</el-button>
<el-button
type="success"
plain
icon="el-icon-edit"
size="medium"
@click="handleImport"
v-hasPermi="['inventory:orders:add']"
>导入</el-button>
<el-button
type="danger"
plain
......@@ -74,6 +82,22 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 新增:订单类型查询项 -->
<el-form-item label="订单类型" prop="orderType">
<el-select
v-model="queryParams.orderType"
placeholder="请选择订单类型"
clearable
style="width: 100%"
>
<el-option
v-for="dict in dict.type.outbound_order_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="批次ID" prop="batchCode">
<el-input
v-model="queryParams.batchCode"
......@@ -174,6 +198,13 @@
<span v-else>-</span>
</template>
</el-table-column>
<!-- 新增:订单类型列 -->
<el-table-column label="订单类型" align="center" prop="orderType" width="120">
<template slot-scope="scope">
<dict-tag v-if="dict.type.outbound_order_type" :options="dict.type.outbound_order_type" :value="scope.row.orderType"/>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="批次ID" align="center" prop="batchCode" width="120" />
<el-table-column label="仓库" align="center" prop="warehouseName" width="120">
<template slot-scope="scope">
......@@ -278,14 +309,29 @@
</el-select>
</el-form-item>
</el-col>
<!-- 新增:订单类型表单项 -->
<el-col :span="12">
<el-form-item label="批次ID" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次ID" :disabled="isViewDetail || formDisabled.batchCode" />
<el-form-item label="订单类型" prop="orderType">
<el-select v-model="form.orderType" placeholder="请选择订单类型" :disabled="isViewDetail || formDisabled.orderType" style="width: 100%">
<el-option
v-for="item in dict.type.outbound_order_type"
:key="item.value"
:label="item.label"
:value="item.value"
>
<span style="margin-left: 8px;">{{ item.label }}</span>
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="批次ID" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次ID" :disabled="isViewDetail || formDisabled.batchCode" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="form.warehouseName"
......@@ -307,6 +353,8 @@
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="货主" prop="ownerId">
<el-input
......@@ -329,8 +377,6 @@
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="出库日期" prop="inboundDate">
<el-date-picker
......@@ -344,14 +390,14 @@
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="目的地" prop="destination">
<el-input v-model="form.destination" placeholder="请输入目的地" :disabled="isViewDetail" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" :disabled="isViewDetail" />
</el-form-item>
......@@ -371,9 +417,11 @@
</el-col>
</el-row>
<!-- 【修改1】新增materialName展示 -->
<div v-for="(group, materialId) in outboundOrderItemsGroup" :key="materialId" class="material-group mb10">
<div class="group-header" style="background: #f5f7fa; padding: 8px 12px; border-radius: 4px; margin-bottom: 8px;">
<span style="font-weight: 600; margin-right: 16px;">物料:{{ materialId+" "+ getMaterialName(materialId) }}</span>
<!-- 【修改2】展示物料名称(优先取分组的materialName,无则用getMaterialName方法) -->
<span style="font-weight: 600; margin-right: 16px;">物料:{{ group.materialName }}</span>
<span style="color: #666;">明细数量:{{ group.items.length }} </span>
<!-- 仅编辑模式显示分组操作按钮 -->
<el-button
......@@ -398,9 +446,13 @@
<!-- 仅编辑模式显示选择列 -->
<el-table-column type="selection" width="50" align="center" v-if="!isViewDetail" />
<el-table-column label="序号" align="center" prop="index" width="50"/>
<el-table-column label="物料编号" prop="materialId" width="180"/>
<el-table-column label="物料名称" prop="materialName" width="180">
<template slot-scope="scope">
{{ scope.row.materialName || '-' }}
</template>
</el-table-column>
<!-- <el-table-column label="仓库编号" prop="warehouseId" width="150" /> -->
<el-table-column label="库位编号" prop="locationId" width="150" />
<el-table-column label="库位编号" prop="locationName" width="150" />
<el-table-column label="批次编号" prop="batchCode" width="150" />
<el-table-column label="计划数量" prop="plannedQuantity" width="150"></el-table-column>
......@@ -462,6 +514,14 @@
@selected="handleLocationSelected"
/>
<import-excel
ref="import"
title="导入"
import-url="/inventory/orders/import"
template-url="inventory/orders/importTemplate"
template-name="owners_importTemplate"
@success="getList"
/>
</div>
</template>
......@@ -474,7 +534,7 @@ import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue"
import OwnerSelector from "@/views/compononents/OwnerSelector.vue"
import PageTitle from "@/components/PageTitle"
import ImportExcel from "@/components/ImportExcel/index"
export default {
name: "Orders",
dicts: ['outbound_order_type', 'inbound_order_type', 'inbound_order_status', 'label_color'],
......@@ -483,7 +543,8 @@ export default {
WarehouseSelector,
LocationSelector,
OwnerSelector,
PageTitle
PageTitle,
ImportExcel
},
data() {
return {
......@@ -510,7 +571,7 @@ export default {
open: false,
// 是否为详细查看模式
isViewDetail: false,
// 明细列表(按物料ID分组){ materialId: { items: [] } }
// 明细列表(按物料ID分组){ materialId: { items: [], materialName: '' } }
outboundOrderItemsGroup: {},
// 选中的明细行
selectedInboundOrderItems: [],
......@@ -521,6 +582,7 @@ export default {
inventoryId: '',
materialUuids: '',
materialId: '',
materialName: '', // 【修改4】新增materialName字段
batchCode: '',
warehouseId: '',
warehouseName: '',
......@@ -550,6 +612,7 @@ export default {
orderId: false,
systemNo: false,
orderTypeId: false,
orderType: false, // 新增:订单类型禁用控制
batchCode: false,
warehouseId: false,
ownerId: false,
......@@ -562,6 +625,7 @@ export default {
orderId: null,
systemNo: null,
orderTypeId: null,
orderType: null, // 新增:订单类型查询参数
batchCode: null,
warehouseId: null,
ownerId: null,
......@@ -580,14 +644,18 @@ export default {
form: {
totalAmount: 0.00,
warehouseName: '',
ownerName: ''
ownerName: '',
ownerId: '', // 【新增】补充货主ID字段
warehouseId: '', // 【新增】补充仓库ID字段
orderType: null, // 新增:订单类型表单字段
},
// 表单校验规则
rules: {
orderId: [{ required: true, message: '请输入出库单号', trigger: 'blur' }],
warehouseId: [{ required: true, message: '请选择仓库', trigger: 'blur' }],
ownerId: [{ required: true, message: '请选择货主', trigger: 'blur' }],
inboundDate: [{ required: true, message: '请选择出库日期', trigger: 'change' }]
inboundDate: [{ required: true, message: '请选择出库日期', trigger: 'change' }],
orderType: [{ required: true, message: '请选择订单类型', trigger: 'change' }], // 新增:订单类型校验
},
// 货主/仓库选择相关
ownerSelectorVisible: false,
......@@ -604,33 +672,14 @@ export default {
created() {
// 延迟加载避免初始化渲染问题
this.$nextTick(() => {
this.getdicts(),
this.getList()
})
},
methods: {
getMaterialName(materialId) {
if (!materialId || !this.materialdicts.length) return '未知物料';
// 精准匹配(如果需要模糊匹配,把 === 改成 includes 即可)
const matchItem = this.materialdicts.find(item =>
String(item.value) === String(materialId)
);
return matchItem ? matchItem.label : '未知物料';
},
getdicts(){
return getMaterialsdicts()
.then(response => {
this.materialdicts = (response.data || response).map(item => ({
value: item.sap_no,
label: item.material_name,
}));
console.log("物料字典数据加载成功:", this.materialdicts);
})
.catch(error => {
console.error("加载物料字典失败:", error);
this.$message.error("物料字典加载失败,请刷新重试");
});
/** 打开导入弹窗 */
handleImport() {
this.$refs.import.show()
},
// 仓库选择回调
handleWarehouseSelected(warehouse) {
......@@ -784,6 +833,7 @@ handleOwnerSelected(owner) {
this.currentDetailItem = this.currentGroupData.items.length > 0
? {
...this.currentGroupData.items[0],
materialName: this.currentGroupData.items[0].materialName || '', // 【修改5】传递物料名称
plannedQuantity: Number(this.currentGroupData.items[0].plannedQuantity) || 0,
actualQuantity: Number(this.currentGroupData.items[0].actualQuantity) || 0,
divisor: Number(this.currentGroupData.items[0].divisor) || 1,
......@@ -798,6 +848,7 @@ handleOwnerSelected(owner) {
inventoryId: '',
materialUuids: '',
materialId: materialId,
materialName: this.outboundOrderItemsGroup[materialId]?.materialName || '', // 【修改6】默认填充分组的物料名称
batchCode: '',
warehouseId: this.form.warehouseId || '',
warehouseName: this.form.warehouseName || '',
......@@ -832,6 +883,7 @@ handleOwnerSelected(owner) {
inventoryId: '',
materialUuids: '',
materialId: materialId || '',
materialName: '', // 【修改7】初始化物料名称
batchCode: '',
warehouseId: this.form.warehouseId || '',
warehouseName: this.form.warehouseName || '',
......@@ -866,6 +918,7 @@ handleOwnerSelected(owner) {
...row,
inventoryId: row.inventoryId || '',
materialUuids: row.materialId || '',
materialName: row.materialName || '', // 【修改8】赋值物料名称
divisor: Number(row.divisor) || 1,
itemStatus: Number(row.itemStatus) || 1,
labelColor: Number(row.labelColor) || 0,
......@@ -900,6 +953,7 @@ handleOwnerSelected(owner) {
if (!this.outboundOrderItemsGroup[materialId]) {
this.outboundOrderItemsGroup[materialId] = {
materialId: materialId,
materialName: detailList[0]?.materialName || '', // 【修改9】初始化分组的物料名称
items: []
};
}
......@@ -915,6 +969,7 @@ handleOwnerSelected(owner) {
orderId: null, // 明细的orderId设为空
outboundOrderId: this.form.id, // 使用主表ID作为outboundOrderId
materialId: materialId,
materialName: item.materialName || group.materialName || '', // 【修改10】保留物料名称
inventoryId: item.inventoryId || '',
itemStatus: Number(item.itemStatus) || 1,
labelColor: Number(item.labelColor) || 0,
......@@ -934,6 +989,8 @@ handleOwnerSelected(owner) {
// 全量替换分组数据
group.items = newDetails;
// 更新分组的物料名称(取第一条的物料名称)
group.materialName = newDetails[0]?.materialName || group.materialName;
this.$message.success(`成功编辑${materialId}物料组,共${newDetails.length}条明细`);
} else {
// 新增模式:按库存ID去重后追加
......@@ -949,6 +1006,7 @@ handleOwnerSelected(owner) {
orderId: null, // 明细的orderId设为空
outboundOrderId: this.form.id || null, // 使用主表ID作为outboundOrderId
materialId: materialId,
materialName: item.materialName || '', // 【修改11】保留物料名称
inventoryId: item.inventoryId || '',
itemStatus: Number(item.itemStatus) || 1,
labelColor: Number(item.labelColor) || 0,
......@@ -972,6 +1030,10 @@ handleOwnerSelected(owner) {
}
group.items = [...group.items, ...newDetails];
// 更新分组的物料名称(如果为空,取第一条的物料名称)
if (!group.materialName) {
group.materialName = newDetails[0]?.materialName || '';
}
this.$message.success(`成功新增${newDetails.length}条明细`);
}
......@@ -1087,6 +1149,7 @@ handleOwnerSelected(owner) {
outboundOrderId: null, // 主表ID,由后端生成
systemNo: null,
orderTypeId: null,
orderType: null, // 新增:订单类型重置
batchCode: null,
warehouseId: null,
warehouseName: '',
......@@ -1112,6 +1175,7 @@ handleOwnerSelected(owner) {
orderId: false,
systemNo: false,
orderTypeId: false,
orderType: false, // 新增:订单类型禁用重置
batchCode: false,
warehouseId: false,
ownerId: false,
......@@ -1141,12 +1205,13 @@ handleOwnerSelected(owner) {
resetQuery() {
// 检查ref存在性
if (this.$refs.queryForm) {
queryParams= {
this.queryParams= {
pageNum: 1,
pageSize: 10,
orderId: null,
systemNo: null,
orderTypeId: null,
orderType: null, // 新增:订单类型重置
batchCode: null,
warehouseId: null,
ownerId: null,
......@@ -1181,6 +1246,7 @@ handleOwnerSelected(owner) {
orderId: false,
systemNo: false,
orderTypeId: false,
orderType: false, // 新增:订单类型启用
batchCode: false,
warehouseId: false,
ownerId: false,
......@@ -1200,10 +1266,13 @@ handleOwnerSelected(owner) {
this.form = {
...response.data,
// outboundOrderId是后端的主键ID,orderId是用户填写的出货单号
orderId: response.data.outboundOrderId || response.data.orderId, // 显示用户填写的出货单号
orderId: response.data.outboundOrderId || response.data.orderId,
warehouseName: response.data.warehouseName || response.data.warehouseId,
ownerName: response.data.ownerName || response.data.ownerId,
totalAmount: 0.00
totalAmount: 0.00,
ownerId: response.data.ownerId || '', // 【新增】赋值货主ID
warehouseId: response.data.warehouseId || '', // 【新增】赋值仓库ID
orderType: response.data.orderType || null, // 新增:订单类型回显
}
if (response.data && response.data.outboundOrderItemsList && Array.isArray(response.data.outboundOrderItemsList)) {
// 按物料ID分组 + 库存ID去重
......@@ -1214,6 +1283,7 @@ handleOwnerSelected(owner) {
if (!groupMap[materialId]) {
groupMap[materialId] = {
materialId: materialId,
materialName: item.materialName || '', // 【修改12】存储分组的物料名称
items: []
}
}
......@@ -1226,6 +1296,7 @@ handleOwnerSelected(owner) {
...item,
index: groupMap[materialId].items.length + 1,
inventoryId: item.inventoryId || '',
materialName: item.materialName || '', // 【修改13】赋值物料名称
divisor: item.divisor !== null ? Number(item.divisor) : 1,
itemStatus: item.itemStatus !== null ? Number(item.itemStatus) : 1,
labelColor: item.labelColor !== null ? Number(item.labelColor) : 0,
......@@ -1265,6 +1336,7 @@ handleOwnerSelected(owner) {
orderId: true, // 编辑时禁用出货单号修改
systemNo: true,
orderTypeId: true,
orderType: true, // 新增:订单类型禁用
batchCode: true,
warehouseId: true,
ownerId: true,
......@@ -1278,7 +1350,10 @@ handleOwnerSelected(owner) {
orderId: response.data.outboundOrderId || response.data.orderId, // 显示用户填写的出货单号
warehouseName: response.data.warehouseName || response.data.warehouseId,
ownerName: response.data.ownerName || response.data.ownerId,
totalAmount: 0.00
totalAmount: 0.00,
ownerId: response.data.ownerId || '', // 【新增】赋值货主ID
warehouseId: response.data.warehouseId || '', // 【新增】赋值仓库ID
orderType: response.data.orderType || null, // 新增:订单类型回显
}
console.log("this.form",this.form)
if (response.data && response.data.outboundOrderItemsList && Array.isArray(response.data.outboundOrderItemsList)) {
......@@ -1290,6 +1365,7 @@ handleOwnerSelected(owner) {
if (!groupMap[materialId]) {
groupMap[materialId] = {
materialId: materialId,
materialName: item.materialName || '', // 【修改14】存储分组的物料名称
items: []
}
}
......@@ -1302,6 +1378,7 @@ handleOwnerSelected(owner) {
...item,
index: groupMap[materialId].items.length + 1,
inventoryId: item.inventoryId || '',
materialName: item.materialName || '', // 【修改15】赋值物料名称
divisor: item.divisor !== null ? Number(item.divisor) : 1,
itemStatus: item.itemStatus !== null ? Number(item.itemStatus) : 1,
labelColor: item.labelColor !== null ? Number(item.labelColor) : 0,
......@@ -1376,19 +1453,16 @@ handleOwnerSelected(owner) {
// 修改点7:构造提交数据,适配新的字段映射规则
const submitData = {
...this.form,
// 关键修改:主表的orderId作为用户填写的出货单号
// 主表的id作为outboundOrderId(新增时为空,由后端生成)
outboundOrderId: this.form.id, // 主表ID作为outboundOrderId
orderId: this.form.orderId, // 用户填写的出货单号
outboundOrderId: this.form.id,
orderId: this.form.orderId,
orderType: this.form.orderType, // 新增:提交订单类型
outboundOrderItemsList: uniqueDetails.map(item => {
const { index, materialUuids, warehouseName, locationName, ...rest } = item
return {
...rest,
// 修改点8:明细的orderId设为空,使用主表的id作为outboundOrderId
orderId: null, // 明细的orderId设为空
outboundOrderId: this.form.id || null, // 使用主表ID作为outboundOrderId
orderId: null,
outboundOrderId: this.form.id || null,
materialName: item.materialName || '', // 【修改16】提交物料名称
inventoryId: rest.inventoryId || '',
materialId: rest.materialId || '',
batchCode: rest.batchCode || '',
......@@ -1448,7 +1522,8 @@ handleOwnerSelected(owner) {
// 适配导出参数,将orderId映射到outboundOrderId
const exportParams = {
...this.queryParams,
outboundOrderId: this.queryParams.orderId // 映射导出参数
outboundOrderId: this.queryParams.orderId, // 映射导出参数
orderType: this.queryParams.orderType, // 新增:导出订单类型参数
}
this.download('inventory/orders/export', exportParams, `orders_${new Date().getTime()}.xlsx`)
}
......
......@@ -236,4 +236,5 @@ public class DictUtils
{
return CacheConstants.SYS_DICT_KEY + configKey;
}
}
......@@ -7,7 +7,7 @@
<groupId>com.ruoyi</groupId>
<version>3.9.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
</parent><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-inventory</artifactId>
......
......@@ -137,30 +137,5 @@ public class OutboundOrderItemsController extends BaseController
{
return toAjax(outboundOrderItemsService.deleteOutboundOrderItemsByIds(ids));
}
/**
* 下载入库单导入模板
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound:importTemplate')")
@Log(title = "入库导入模板", businessType = BusinessType.IMPORT)
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
ExcelUtil<InboundTemplateVO> util = new ExcelUtil<InboundTemplateVO>(InboundTemplateVO.class);
util.importTemplateExcel(response, "入库单及入库物料明细信息");
}
/**
* 导入入库单物料明细
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound:import')")
@Log(title = "入库信息导入", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public AjaxResult importTemplate(MultipartFile file , boolean updateSupport) throws Exception
{
ExcelUtil<OutboundTemplateVO> util = new ExcelUtil<OutboundTemplateVO>(OutboundTemplateVO.class);
List<OutboundTemplateVO> inboundOrders = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = outboundOrderItemsService.importOutoundOrders(inboundOrders, updateSupport, operName);
return success(message);
}
}
......@@ -5,6 +5,8 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.vo.InboundTemplateVO;
import com.ruoyi.inventory.domain.vo.OutboundTemplateVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
......@@ -23,6 +25,7 @@ import com.ruoyi.inventory.domain.OutboundOrders;
import com.ruoyi.inventory.service.IOutboundOrdersService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* 出库单主Controller
......@@ -136,5 +139,30 @@ public class OutboundOrdersController extends BaseController
String resultMap = outboundOrdersService.outboundOrdersCount();
return AjaxResult.success(resultMap);
}
/**
* 下载入库单导入模板
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound:importTemplate')")
@Log(title = "入库导入模板", businessType = BusinessType.IMPORT)
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
ExcelUtil<InboundTemplateVO> util = new ExcelUtil<InboundTemplateVO>(InboundTemplateVO.class);
util.importTemplateExcel(response, "入库单及入库物料明细信息");
}
/**
* 导入入库单物料明细
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound:import')")
@Log(title = "入库信息导入", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public AjaxResult importTemplate(MultipartFile file , boolean updateSupport) throws Exception
{
ExcelUtil<OutboundTemplateVO> util = new ExcelUtil<OutboundTemplateVO>(OutboundTemplateVO.class);
List<OutboundTemplateVO> inboundOrders = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = outboundOrdersService.importOutboundOrders(inboundOrders, updateSupport, operName);
return success(message);
}
}
......@@ -4,6 +4,7 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.inventory.domain.vo.OwnerTemplateVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
......@@ -67,8 +68,8 @@ public class OwnersController extends BaseController
@PostMapping("/import")
public AjaxResult importTemplate(MultipartFile file , boolean updateSupport) throws Exception
{
ExcelUtil<Owners> util = new ExcelUtil<Owners>(Owners.class);
List<Owners> ownersList = util.importExcel(file.getInputStream());
ExcelUtil<OwnerTemplateVO> util = new ExcelUtil<OwnerTemplateVO>(OwnerTemplateVO.class);
List<OwnerTemplateVO> ownersList = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = ownersService.importOwners(ownersList, updateSupport, operName);
return success(message);
......@@ -77,7 +78,7 @@ public class OwnersController extends BaseController
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
ExcelUtil<Owners> util = new ExcelUtil<Owners>(Owners.class);
ExcelUtil<OwnerTemplateVO> util = new ExcelUtil<OwnerTemplateVO>(OwnerTemplateVO.class);
util.importTemplateExcel(response, "货主数据");
}
......
......@@ -4,6 +4,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.inventory.domain.Owners;
import com.ruoyi.inventory.domain.vo.OwnerTemplateVO;
import com.ruoyi.inventory.domain.vo.StorageLocationsLocationTemplateVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
......@@ -15,6 +19,7 @@ import com.ruoyi.inventory.domain.StorageLocations;
import com.ruoyi.inventory.service.IStorageLocationsService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* 库位Controller
......@@ -124,4 +129,23 @@ public class StorageLocationsController extends BaseController
List<StorageLocations> list = storageLocationsService.getStorageLocationsList(storageLocations);
return getDataTable(list);
}
@PreAuthorize("@ss.hasPermi('inventory:owners:add')")
@Log(title = "货主信息", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public AjaxResult importTemplate(MultipartFile file , boolean updateSupport) throws Exception
{
ExcelUtil<StorageLocationsLocationTemplateVO> util = new ExcelUtil<StorageLocationsLocationTemplateVO>(StorageLocationsLocationTemplateVO.class);
List<StorageLocationsLocationTemplateVO> storageLocationsLocationTemplateVOS = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = storageLocationsService.importStorageLocationsLocation(storageLocationsLocationTemplateVOS, updateSupport, operName);
return success(message);
}
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
ExcelUtil<StorageLocationsLocationTemplateVO> util = new ExcelUtil<StorageLocationsLocationTemplateVO>(StorageLocationsLocationTemplateVO.class);
util.importTemplateExcel(response, "货主数据");
}
}
......@@ -28,9 +28,13 @@ public class Inventory extends BaseEntity
@Excel(name = "入库单号")
private String orderId;
/** 货物名称 */
private String orderName;
/** 物料ID 检索条件 */
@Excel(name = "物料ID 检索条件")
private String materialId;
/** 货物名称 */
private String materialName;
/** 批次ID 检索条件 */
@Excel(name = "批次ID 检索条件")
......@@ -40,15 +44,20 @@ public class Inventory extends BaseEntity
private String warehousesId;
/** 仓库编码 检索条件 */
private String warehousesCode;
/** 仓库编码 检索条件 */
private String warehousesName;
/** 库位ID 检索条件 */
@Excel(name = "库位ID 检索条件")
private String locationId;
/** 库位名称 */
private String locationName;
/** 货主ID 检索条件 */
@Excel(name = "货主ID 检索条件")
private String ownerId;
private String ownerName;
/** 库存数量 */
@Excel(name = "库存数量")
private Long quantity;
......@@ -112,6 +121,54 @@ public class Inventory extends BaseEntity
/** 预警类型 */
private String alertType;
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getWarehousesName() {
return warehousesName;
}
public void setWarehousesName(String warehousesName) {
this.warehousesName = warehousesName;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public String getWarehousesCode() {
return warehousesCode;
}
public void setWarehousesCode(String warehousesCode) {
this.warehousesCode = warehousesCode;
}
public String getOwnerName() {
return ownerName;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
public String getWarehousesId() {
return warehousesId;
}
......@@ -330,16 +387,6 @@ public class Inventory extends BaseEntity
return updateUserCode;
}
public void setWarehousesCode(String warehousesCode)
{
this.warehousesCode = warehousesCode;
}
public String getWarehousesCode()
{
return warehousesCode;
}
public void setAlertType(String alertType)
{
this.alertType = alertType;
......@@ -353,29 +400,37 @@ public class Inventory extends BaseEntity
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("inventoryType", getInventoryType())
.append("orderId", getOrderId())
.append("materialId", getMaterialId())
.append("batchId", getBatchId())
.append("locationId", getLocationId())
.append("ownerId", getOwnerId())
.append("quantity", getQuantity())
.append("lockedQuantity", getLockedQuantity())
.append("unitWeight", getUnitWeight())
.append("totalWeight", getTotalWeight())
.append("totalVolume", getTotalVolume())
.append("productionDate", getProductionDate())
.append("expirationDate", getExpirationDate())
.append("inventoryStatus", getInventoryStatus())
.append("lastInboundTime", getLastInboundTime())
.append("lastOutboundTime", getLastOutboundTime())
.append("isUsed", getIsUsed())
.append("sortNo", getSortNo())
.append("createTime", getCreateTime())
.append("createUserCode", getCreateUserCode())
.append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode())
.toString();
.append("id", getId())
.append("inventoryType", getInventoryType())
.append("orderId", getOrderId())
.append("orderName", getOrderName())
.append("materialId", getMaterialId())
.append("materialName", getMaterialName())
.append("batchId", getBatchId())
.append("warehousesId", getWarehousesId())
.append("warehousesName", getWarehousesName())
.append("warehousesCode", getWarehousesCode())
.append("locationId", getLocationId())
.append("locationName", getLocationName())
.append("ownerId", getOwnerId())
.append("ownerName", getOwnerName())
.append("quantity", getQuantity())
.append("lockedQuantity", getLockedQuantity())
.append("unitWeight", getUnitWeight())
.append("totalWeight", getTotalWeight())
.append("totalVolume", getTotalVolume())
.append("productionDate", getProductionDate())
.append("expirationDate", getExpirationDate())
.append("inventoryStatus", getInventoryStatus())
.append("lastInboundTime", getLastInboundTime())
.append("lastOutboundTime", getLastOutboundTime())
.append("isUsed", getIsUsed())
.append("sortNo", getSortNo())
.append("createTime", getCreateTime())
.append("createUserCode", getCreateUserCode())
.append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode())
.append("alertType", getAlertType())
.toString();
}
}
......@@ -3,6 +3,7 @@ package com.ruoyi.inventory.domain;
import java.util.List;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
......@@ -14,6 +15,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
* @author ruoyi
* @date 2025-12-03
*/
@Data
public class OutboundOrders extends BaseEntity
{
private static final long serialVersionUID = 1L;
......@@ -57,6 +59,8 @@ public class OutboundOrders extends BaseEntity
@Excel(name = "出库单状态1-草稿 2-已完成 3-已取消 字典,检索条件")
private Long orderStatus;
/** 出库日期 日期无时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "出库日期 日期无时间", width = 30, dateFormat = "yyyy-MM-dd")
......@@ -86,6 +90,8 @@ public class OutboundOrders extends BaseEntity
@Excel(name = "排序")
private Long sortNo;
private Long orderType;
/** 创建日期 */
@Excel(name = "创建日期")
private String createUserCode;
......@@ -97,230 +103,4 @@ public class OutboundOrders extends BaseEntity
/** 出库单明细信息 */
private List<OutboundOrderItems> outboundOrderItemsList;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void setOrderId(String orderId)
{
this.orderId = orderId;
}
public String getOrderId()
{
return orderId;
}
public void setSystemNo(String systemNo)
{
this.systemNo = systemNo;
}
public String getSystemNo()
{
return systemNo;
}
public void setOrderTypeId(String orderTypeId)
{
this.orderTypeId = orderTypeId;
}
public String getOrderTypeId()
{
return orderTypeId;
}
public void setBatchCode(String batchCode)
{
this.batchCode = batchCode;
}
public String getBatchCode()
{
return batchCode;
}
public void setWarehouseId(String warehouseId)
{
this.warehouseId = warehouseId;
}
public String getWarehouseId()
{
return warehouseId;
}
public void setOwnerId(String ownerId)
{
this.ownerId = ownerId;
}
public String getOwnerId()
{
return ownerId;
}
public void setOrderStatus(Long orderStatus)
{
this.orderStatus = orderStatus;
}
public Long getOrderStatus()
{
return orderStatus;
}
public void setInboundDate(Date inboundDate)
{
this.inboundDate = inboundDate;
}
public Date getInboundDate()
{
return inboundDate;
}
public void setDestination(String destination)
{
this.destination = destination;
}
public String getDestination()
{
return destination;
}
public void setTotalPlannedQuantity(Long totalPlannedQuantity)
{
this.totalPlannedQuantity = totalPlannedQuantity;
}
public Long getTotalPlannedQuantity()
{
return totalPlannedQuantity;
}
public void setTotalActualQuantity(Long totalActualQuantity)
{
this.totalActualQuantity = totalActualQuantity;
}
public Long getTotalActualQuantity()
{
return totalActualQuantity;
}
public void setTotalPackages(Long totalPackages)
{
this.totalPackages = totalPackages;
}
public Long getTotalPackages()
{
return totalPackages;
}
public void setIsUsed(Long isUsed)
{
this.isUsed = isUsed;
}
public Long getIsUsed()
{
return isUsed;
}
public void setSortNo(Long sortNo)
{
this.sortNo = sortNo;
}
public Long getSortNo()
{
return sortNo;
}
public void setCreateUserCode(String createUserCode)
{
this.createUserCode = createUserCode;
}
public String getCreateUserCode()
{
return createUserCode;
}
public void setUpdateUserCode(String updateUserCode)
{
this.updateUserCode = updateUserCode;
}
public String getUpdateUserCode()
{
return updateUserCode;
}
public List<OutboundOrderItems> getOutboundOrderItemsList()
{
return outboundOrderItemsList;
}
public void setOutboundOrderItemsList(List<OutboundOrderItems> outboundOrderItemsList)
{
this.outboundOrderItemsList = outboundOrderItemsList;
}
// 补充 warehouseName 的 getter/setter 方法
public String getWarehouseName() {
return warehouseName;
}
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
// 补充 ownerName 的 getter/setter 方法
public String getOwnerName() {
return ownerName;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("orderId", getOrderId())
.append("systemNo", getSystemNo())
.append("orderTypeId", getOrderTypeId())
.append("batchCode", getBatchCode())
.append("warehouseId", getWarehouseId())
.append("warehouseName", getWarehouseName()) // 新增
.append("ownerId", getOwnerId())
.append("ownerName", getOwnerName()) // 新增
.append("orderStatus", getOrderStatus())
.append("inboundDate", getInboundDate())
.append("destination", getDestination())
.append("totalPlannedQuantity", getTotalPlannedQuantity())
.append("totalActualQuantity", getTotalActualQuantity())
.append("totalPackages", getTotalPackages())
.append("remark", getRemark())
.append("isUsed", getIsUsed())
.append("sortNo", getSortNo())
.append("createTime", getCreateTime())
.append("createUserCode", getCreateUserCode())
.append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode())
.append("outboundOrderItemsList", getOutboundOrderItemsList())
.toString();
}
}
\ No newline at end of file
......@@ -28,8 +28,11 @@ public class Owners extends BaseEntity
@Excel(name = "货主名称")
private String ownerName;
@Excel(name = "货主名称")
private String englishName;
/** 货主类型 1-供应商 2-客户 3-内部 检索条件 */
@Excel(name = "货主类型",dictType="owner_type")
@Excel(name = "货主类型")
private Long ownerType;
/** 联系人 */
......@@ -123,7 +126,15 @@ public class Owners extends BaseEntity
return contactPerson;
}
public void setContactPhone(String contactPhone)
public String getEnglishName() {
return englishName;
}
public void setEnglishName(String englishName) {
this.englishName = englishName;
}
public void setContactPhone(String contactPhone)
{
this.contactPhone = contactPhone;
}
......@@ -237,6 +248,7 @@ public class Owners extends BaseEntity
.append("taxNumber", getTaxNumber())
.append("bankAccount", getBankAccount())
.append("isActive", getIsActive())
.append("english_name", getEnglishName())
.append("sortNo", getSortNo())
.append("createTime", getCreateTime())
.append("createUserCode", getCreateUserCode())
......
......@@ -26,6 +26,44 @@ public class StorageLocations extends BaseEntity
@Excel(name = "库位编码 检索条件")
private String locationCode;
/**
* 上架顺序(数字越小优先级越高)
*/
private String putawayOrder;
/**
* 拣货顺序(数字越小优先级越高)
*/
private String pickingOrder;
/**
* 库位使用(
*/
private Integer LocationUsage;
/**
* 库位处理状态(如:正常/冻结/锁定/禁用)
*/
private String locationHandling;
/**
* 周转需求(如:高周转/中周转/低周转)
*/
private String turnoverDemand;
/**
* 所属拣货区域(编码/名称)
*/
private String pickingArea;
/**
* 是否允许混放产品(true=允许,false=不允许)
*/
private String allowMixedProducts;
/**
* 是否允许混放批次(true=允许,false=不允许)
*/
private String allowMixedBatches;
/** 库位名称 检索条件 */
@Excel(name = "库位名称 检索条件")
private String locationName;
......@@ -77,7 +115,7 @@ public class StorageLocations extends BaseEntity
@Excel(name = "温区")
private String temperatureZone;
/** 应用状态1使用0未使用 */
/** 库位属性 */
@Excel(name = "应用状态1使用0未使用")
private Long isEnabled;
......
......@@ -10,120 +10,122 @@ import java.util.Date;
/**
* 出库单明细对象 outbound_order_items
*
*
* @author ruoyi
* @date 2025-12-03
*/
public class OutboundTemplateVO extends BaseEntity
{
public class OutboundTemplateVO extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 编号 */
private String id;
/** 入库单号 检索条件 */
@Excel(name = "入库单号")
private String orderId;
/** 系统编号 检索条件 */
@Excel(name = "系统编号")
private String systemNo;
/** 入库类型 字典,检索条件 */
@Excel(name = "入库类型")
private String orderTypeId;
/** 批次ID 检索条件 */
@Excel(name = "批次ID")
private String batchId;
/** 入库日期 日期无时间 */
/** 日期(入库日期) */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "入库日期", width = 30, dateFormat = "yyyy-MM-dd")
@Excel(name = "日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date inboundDate;
/** 订单类型 字典,检索条件 */
@Excel(name = "订单类型")
private String orderType;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 货主ID */
@Excel(name = "货主ID")
private String ownerId;
/** 仓库ID 暂无用 */
@Excel(name = "仓库ID")
private String warehouseId;
/** 库位ID 检索条件 */
@Excel(name = "库位ID")
private String locationId;
/** 货物ID 字典,检索条件 */
@Excel(name = "SAP号")
/** SAP号 */
@Excel(name = "SAP No")
private String sapNo;
/** 货物ID 字典,检索条件 */
@Excel(name = "货物名称")
/** 物料ID */
private String materialId;
/** 货物名称 */
@Excel(name = "物料名称")
private String materialName;
/** 负责人 暂无用 */
// @Excel(name = "负责人 暂无用")
private String opUserName;
/** TS Code */
@Excel(name = "TS Code")
private String tsCode;
/** 批号 */
@Excel(name = " 批号")
private String batchCode;
/** 计划数量 */
@Excel(name = "计划数量")
private Long plannedQuantity;
/** 实际数量 */
@Excel(name = "实际数量")
/** 件重 */
@Excel(name = "件重")
private Long pieceWeight;
/** 件数(实际件数) */
@Excel(name = "件数")
private Long actualPackages;
/** 实发数量(实际数量) */
@Excel(name = "实发数量")
private Long actualQuantity;
/** 计划件数 暂无用 */
// @Excel(name = "计划件数")
private Long plannedPackages;
/** 库位名称 */
@Excel(name = "库位")
private String locationName;
/** 实际件数 */
@Excel(name = "实际件数")
private Long actualPackages;
/** 库位ID */
private String locationId;
/** 约数 */
@Excel(name = "约数")
private Long divisor;
/** 仓库ID */
private String warehouseId;
/** 仓库名称 */
@Excel(name = "仓库")
private String warehouseName;
/** 标签颜色 字典,检索条件 */
@Excel(name = "标签颜色")
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 标签颜色 */
@Excel(name = "标签颜色",dictType = "label_color")
private Long labelColor;
/** 凭证号 检索条件 */
/** 凭证号 */
@Excel(name = "凭证号")
private String voucherNumber;
/** 单价 */
@Excel(name = "单价")
private Long unitPrice;
/** 保温状态/类型 */
@Excel(name = "保温")
private String insulation;
/** 危检类别(危险类别) */
@Excel(name = "危险类别")
private String dangerCheckType;
/** 单号 */
@Excel(name = "单号")
private String orderId;
/** 系统编号(系统单号) */
@Excel(name = "系统单号")
private String systemNo;
/** 收货人 */
@Excel(name = "收货人")
private String receivedBy;
/** 订单类型 */
@Excel(name = "订单类型")
private String orderType;
/** 物料备注 */
@Excel(name = "物料备注")
private String remark2;
/** 货主ID */
private String ownerId;
/** 排序号 */
private Long sortNo;
/** 货主名称 */
@Excel(name = "货主")
private String ownerName;
/** 创建日期 */
private String createUserCode;
/** 目的地 */
@Excel(name = "目的地")
private String destination;
/** 预留 */
@Excel(name = "预留")
private String reservation;
private String updateUserCode;
/** 单个件重值(单件重量) */
@Excel(name = "单件重量")
private Long singlePieceWeight;
// ===================== Getter & Setter 完整实现 =====================
public String getId() {
return id;
}
......@@ -132,241 +134,257 @@ public class OutboundTemplateVO extends BaseEntity
this.id = id;
}
public String getOrderId() {
return orderId;
public Date getInboundDate() {
return inboundDate;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
public void setInboundDate(Date inboundDate) {
this.inboundDate = inboundDate;
}
public String getSystemNo() {
return systemNo;
public String getSapNo() {
return sapNo;
}
public void setSystemNo(String systemNo) {
this.systemNo = systemNo;
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public String getOrderTypeId() {
return orderTypeId;
public void setTsCode(String tsCode) {
this.tsCode = tsCode;
}
public void setOrderTypeId(String orderTypeId) {
this.orderTypeId = orderTypeId;
public String getBatchCode() {
return batchCode;
}
public String getBatchId() {
return batchId;
public void setBatchCode(String batchCode) {
this.batchCode = batchCode;
}
public void setBatchId(String batchId) {
this.batchId = batchId;
public String getMaterialId() {
return materialId;
}
public Date getInboundDate() {
return inboundDate;
public void setMaterialId(String materialId) {
this.materialId = materialId;
}
public void setInboundDate(Date inboundDate) {
this.inboundDate = inboundDate;
public String getMaterialName() {
return materialName;
}
public String getOrderType() {
return orderType;
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
public String getTsCode() {
return tsCode;
}
public String getRemark() {
return remark;
public void setTsCo(String tsCode) {
this.tsCode = tsCode;
}
public void setRemark(String remark) {
this.remark = remark;
public Long getPlannedQuantity() {
return plannedQuantity;
}
public String getOwnerId() {
return ownerId;
public void setPlannedQuantity(Long plannedQuantity) {
this.plannedQuantity = plannedQuantity;
}
public void setOwnerId(String ownerId) {
this.ownerId = ownerId;
public Long getPieceWeight() {
return pieceWeight;
}
public String getWarehouseId() {
return warehouseId;
public void setPieceWeight(Long pieceWeight) {
this.pieceWeight = pieceWeight;
}
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
public Long getActualPackages() {
return actualPackages;
}
public String getLocationId() {
return locationId;
public void setActualPackages(Long actualPackages) {
this.actualPackages = actualPackages;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
public Long getActualQuantity() {
return actualQuantity;
}
public String getRemark2() {
return remark2;
public void setActualQuantity(Long actualQuantity) {
this.actualQuantity = actualQuantity;
}
public void setRemark2(String remark2) {
this.remark2 = remark2;
public String getLocationName() {
return locationName;
}
public String getSapNo() {
return sapNo;
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
public String getLocationId() {
return locationId;
}
public String getMaterialName() {
return materialName;
public void setLocationId(String locationId) {
this.locationId = locationId;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
public String getWarehouseId() {
return warehouseId;
}
public String getOpUserName() {
return opUserName;
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
}
public void setOpUserName(String opUserName) {
this.opUserName = opUserName;
public String getWarehouseName() {
return warehouseName;
}
public Long getPlannedQuantity() {
return plannedQuantity;
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
public void setPlannedQuantity(Long plannedQuantity) {
this.plannedQuantity = plannedQuantity;
public String getRemark() {
return remark;
}
public Long getActualQuantity() {
return actualQuantity;
public void setRemark(String remark) {
this.remark = remark;
}
public void setActualQuantity(Long actualQuantity) {
this.actualQuantity = actualQuantity;
public Long getLabelColor() {
return labelColor;
}
public Long getPlannedPackages() {
return plannedPackages;
public void setLabelColor(Long labelColor) {
this.labelColor = labelColor;
}
public void setPlannedPackages(Long plannedPackages) {
this.plannedPackages = plannedPackages;
public String getVoucherNumber() {
return voucherNumber;
}
public Long getActualPackages() {
return actualPackages;
public void setVoucherNumber(String voucherNumber) {
this.voucherNumber = voucherNumber;
}
public void setActualPackages(Long actualPackages) {
this.actualPackages = actualPackages;
public String getInsulation() {
return insulation;
}
public Long getDivisor() {
return divisor;
public void setInsulation(String insulation) {
this.insulation = insulation;
}
public void setDivisor(Long divisor) {
this.divisor = divisor;
public String getDangerCheckType() {
return dangerCheckType;
}
public Long getLabelColor() {
return labelColor;
public void setDangerCheckType(String dangerCheckType) {
this.dangerCheckType = dangerCheckType;
}
public void setLabelColor(Long labelColor) {
this.labelColor = labelColor;
public String getOrderId() {
return orderId;
}
public String getVoucherNumber() {
return voucherNumber;
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public void setVoucherNumber(String voucherNumber) {
this.voucherNumber = voucherNumber;
public String getSystemNo() {
return systemNo;
}
public Long getUnitPrice() {
return unitPrice;
public void setSystemNo(String systemNo) {
this.systemNo = systemNo;
}
public String getOrderType() {
return orderType;
}
public void setUnitPrice(Long unitPrice) {
this.unitPrice = unitPrice;
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getOwnerId() {
return ownerId;
}
public void setOwnerId(String ownerId) {
this.ownerId = ownerId;
}
public String getReceivedBy() {
return receivedBy;
public String getOwnerName() {
return ownerName;
}
public void setReceivedBy(String receivedBy) {
this.receivedBy = receivedBy;
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
public String getCreateUserCode() {
return createUserCode;
public String getDestination() {
return destination;
}
public void setCreateUserCode(String createUserCode) {
this.createUserCode = createUserCode;
public void setDestination(String destination) {
this.destination = destination;
}
public String getUpdateUserCode() {
return updateUserCode;
public String getReservation() {
return reservation;
}
public void setUpdateUserCode(String updateUserCode) {
this.updateUserCode = updateUserCode;
public void setReservation(String reservation) {
this.reservation = reservation;
}
public Long getSortNo() {
return sortNo;
public Long getSinglePieceWeight() {
return singlePieceWeight;
}
public void setSortNo(Long sortNo) {
this.sortNo = sortNo;
public void setSinglePieceWeight(Long singlePieceWeight) {
this.singlePieceWeight = singlePieceWeight;
}
@Override
public String toString() {
return "InboundTemplateVO{" +
"id='" + id + '\'' +
", orderId='" + orderId + '\'' +
", systemNo='" + systemNo + '\'' +
", orderTypeId='" + orderTypeId + '\'' +
", batchId='" + batchId + '\'' +
", inboundDate=" + inboundDate +
", orderType='" + orderType + '\'' +
", remark1='" + remark + '\'' +
", ownerId='" + ownerId + '\'' +
", warehouseId='" + warehouseId + '\'' +
", locationId='" + locationId + '\'' +
", sapNo='" + sapNo + '\'' +
", materialName='" + materialName + '\'' +
", opUserName='" + opUserName + '\'' +
", plannedQuantity=" + plannedQuantity +
", actualQuantity=" + actualQuantity +
", plannedPackages=" + plannedPackages +
", actualPackages=" + actualPackages +
", divisor=" + divisor +
", labelColor=" + labelColor +
", voucherNumber='" + voucherNumber + '\'' +
", unitPrice=" + unitPrice +
", receivedBy='" + receivedBy + '\'' +
", remark2='" + remark2 + '\'' +
'}';
}
}
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", id)
.append("inboundDate", inboundDate)
.append("sapNo", sapNo)
.append("materialId", materialId)
.append("materialName", materialName)
.append("tsCode", tsCode)
.append("plannedQuantity", plannedQuantity)
.append("pieceWeight", pieceWeight)
.append("actualPackages", actualPackages)
.append("actualQuantity", actualQuantity)
.append("locationName", locationName)
.append("locationId", locationId)
.append("warehouseId", warehouseId)
.append("warehouseName", warehouseName)
.append("remark", remark)
.append("labelColor", labelColor)
.append("voucherNumber", voucherNumber)
.append("insulation", insulation)
.append("dangerCheckType", dangerCheckType)
.append("orderId", orderId)
.append("systemNo", systemNo)
.append("orderType", orderType)
.append("ownerId", ownerId)
.append("ownerName", ownerName)
.append("destination", destination)
.append("reservation", reservation)
.append("singlePieceWeight", singlePieceWeight)
.toString();
}
}
\ No newline at end of file
package com.ruoyi.inventory.domain.vo;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
/**
* 客户信息实体类
*
* @author 豆包编程助手
* @date 2025-12-11
*/
@Data
public class OwnerTemplateVO {
/**
* 客户编码/客户名称(根据业务场景调整,若为编码建议命名为 customerCode)
*/
@Excel(name = "客户")
private String ownerCode;
/**
* 激活状态(如:是/否、已激活/未激活,建议用布尔值或枚举)
*/
@Excel(name = "激活",dictType = "yorn")
private String isActive;
/**
* 客户类型(如:个人/企业、经销商/终端客户等)
*/
@Excel(name = "类型",dictType="owner_type")
private String ownerType;
/**
* 客户中文名称
*/
@Excel(name = "中文名称")
private String ownerName;
/**
* 客户英文名称
*/
@Excel(name = "英文名称")
private String englishName;
/**
* 地址1(主地址)
*/
@Excel(name = "地址1")
private String address;
/**
* 联系人1(主要联系人)
*/
@Excel(name = "电话1")
private String contactPerson;
/**
* 电话1(主要联系电话)
*/
@Excel(name = "联系人1")
private String contactPhone;
}
\ No newline at end of file
package com.ruoyi.inventory.domain.vo;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Log;
import lombok.Data;
/**
* 库位信息实体类
*
* @author 豆包编程助手
* @date 2025-12-11
*/
@Data
public class StorageLocationsLocationTemplateVO {
@Excel(name = "库位编码")
private String locationCode;
@Excel(name = "上架顺序")
private String putawayOrder;
@Excel(name = "拣货顺序")
private String pickingOrder;
@Excel(name = "库位使用",dictType = "location_usage")
private String LocationUsage;
@Excel(name = "库位类型",dictType = "location_type")
private String locationType;
@Excel(name = "库位属性",dictType = "is_enabled")
private String isEnabled;
@Excel(name = "库位处理")
private String locationHandling;
@Excel(name = "周转需求")
private String turnoverDemand;
@Excel(name = "上架区")
private String zoneCode;
@Excel(name = "拣货区")
private String pickingArea;
@Excel(name = "允许混放产品",dictType="yorn")
private String allowMixedProducts;
@Excel(name = "允许混放批次")
private String allowMixedBatches;
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ public interface OutboundOrderItemsMapper
public int deleteOutboundOrderItemsById(String[] ids);
public int batchInsertOutboundOrderItems(List<InboundOrderItems> inboundOrderItems);
public int batchInsertOutboundOrderItems(List<OutboundOrderItems> inboundOrderItems);
}
......@@ -2,6 +2,7 @@ package com.ruoyi.inventory.mapper;
import java.util.List;
import com.ruoyi.common.annotation.SerialExecution;
import com.ruoyi.inventory.domain.OutboundOrderItems;
import com.ruoyi.inventory.domain.OutboundOrderLog;
......@@ -96,6 +97,7 @@ public interface OutboundOrderLogMapper
* @param outboundOrderItemsList 出库单明细列表
* @return 结果
*/
public int batchOutboundOrderLog(List<OutboundOrderLog> outboundOrderLogs);
}
......@@ -61,5 +61,6 @@ public interface OwnersMapper
*/
public int deleteOwnersByIds(String[] ids);
public int batchInsertOwners(List<Owners> list);
}
......@@ -97,4 +97,7 @@ public interface StorageLocationsMapper
* @return 库位集合
*/
List<StorageLocations> getStorageLocationsList(StorageLocations storageLocations);
int batchInsertStorageLocations(List<StorageLocations> storageLocations);
}
......@@ -70,6 +70,4 @@ public interface IOutboundOrderItemsService
public int deleteOutboundOrderItemsById(String id);
@Transactional(rollbackFor = Exception.class)
String importOutoundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName);
}
......@@ -4,6 +4,8 @@ import java.util.List;
import java.util.Map;
import com.ruoyi.inventory.domain.OutboundOrders;
import com.ruoyi.inventory.domain.vo.OutboundTemplateVO;
import org.springframework.transaction.annotation.Transactional;
/**
* 出库单主Service接口
......@@ -74,4 +76,7 @@ public interface IOutboundOrdersService
public List<Map<String,String>> outboundOrdersTopTenByAmount();
public String outboundOrdersCount();
@Transactional(rollbackFor = Exception.class)
String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName);
}
......@@ -2,6 +2,7 @@ package com.ruoyi.inventory.service;
import java.util.List;
import com.ruoyi.inventory.domain.Owners;
import com.ruoyi.inventory.domain.vo.OwnerTemplateVO;
/**
* 货主信息Service接口
......@@ -42,7 +43,7 @@ public interface IOwnersService
* @param ownersList 货主信息
* @return 结果
*/
public String importOwners(List<Owners> ownersList, Boolean isUpdateSupport, String operName);
public String importOwners(List<OwnerTemplateVO> ownersList, Boolean isUpdateSupport, String operName);
/**
* 修改货主信息
......@@ -67,4 +68,5 @@ public interface IOwnersService
* @return 结果
*/
public int deleteOwnersById(String id);
}
......@@ -5,6 +5,9 @@ import java.util.List;
import java.util.Map;
import com.ruoyi.inventory.domain.StorageLocations;
import com.ruoyi.inventory.domain.vo.OutboundTemplateVO;
import com.ruoyi.inventory.domain.vo.OwnerTemplateVO;
import com.ruoyi.inventory.domain.vo.StorageLocationsLocationTemplateVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
......@@ -97,4 +100,7 @@ public interface IStorageLocationsService
* @return 库位集合
*/
public List<StorageLocations> getStorageLocationsList(StorageLocations storageLocations);
public String importStorageLocationsLocation(List<StorageLocationsLocationTemplateVO> ownersList, Boolean isUpdateSupport, String operName);
}
......@@ -4,6 +4,7 @@ import java.util.*;
import java.util.stream.Collectors;
import com.ruoyi.common.annotation.SerialExecution;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.inventory.domain.InboundOrderItems;
import com.ruoyi.inventory.domain.OutboundOrderItems;
......@@ -134,21 +135,26 @@ public class InventoryServiceImpl implements IInventoryService
@Override
public int ship(List<OutboundOrderItems> outboundOrderItems)
{
if (!outboundOrderItems.isEmpty()) {
List<String> inventoryIds = outboundOrderItems.stream().map(OutboundOrderItems::getInventoryId).collect(Collectors.toList());
for (OutboundOrderItems outboundOrderItem : outboundOrderItems) {
OutboundOrderLog outboundOrderLog = outboundOrderLogMapper.selectOutboundOrderLogById(outboundOrderItem.getId());
Inventory inventory =inventoryMapper.selectInventoryById(outboundOrderLog.getInventoryId());
inventory.setQuantity(inventory.getQuantity()-outboundOrderItem.getActualQuantity());
if (inventory.getQuantity()==0){
inventory.setInventoryStatus(0l);
}
updateInventory(inventory);
}
RefreshInventory(inventoryIds);
}
return 1;
if (!outboundOrderItems.isEmpty()) {
List<String> inventoryIds = outboundOrderItems.stream().map(OutboundOrderItems::getInventoryId).collect(Collectors.toList());
for (OutboundOrderItems outboundOrderItem : outboundOrderItems) {
OutboundOrderLog outboundOrderLog = outboundOrderLogMapper.selectOutboundOrderLogById(outboundOrderItem.getId());
// ========== 新增空值校验(兜底) ==========
if (outboundOrderLog == null) {
throw new ServiceException("明细ID【" + outboundOrderItem.getId() + "】对应的出库日志不存在");
}
// ==========================================
Inventory inventory =inventoryMapper.selectInventoryById(outboundOrderLog.getInventoryId());
inventory.setQuantity(inventory.getQuantity()-outboundOrderItem.getActualQuantity());
if (inventory.getQuantity()==0){
inventory.setInventoryStatus(0l);
}
updateInventory(inventory);
}
RefreshInventory(inventoryIds);
}
return 1;
}
@SerialExecution(group = "inventoryRefresh", fair = true)
......
......@@ -109,154 +109,5 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
return outboundOrderItemsMapper.deleteOutboundOrderItemsById(id);
}
/**
* 导入入库单明细信息
*
* @param inboundOrdersList,isUpdateSupport,operName 入库单数据信息
* @return 结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public String importOutoundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName) {
if (StringUtils.isNull(inboundOrdersList) || inboundOrdersList.size() == 0) {
throw new ServiceException("导入数据不能为空!");
}
// 2. 初始化统计变量
int totalMainSuccess = 0; // 成功的主表数量
int totalMainFailure = 0; // 失败的主表数量
int totalItemSuccess = 0; // 成功的明细数量
int totalItemFailure = 0; // 失败的明细数量
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
Date now = DateUtils.getNowDate();
Long userId = SecurityUtils.getUserId();
String operId = userId.toString();
// 3. 按入库单号分组(核心:同一入库单的多条明细归为一组)
Map<String, List<OutboundTemplateVO>> orderGroupMap = inboundOrdersList.stream()
.filter(vo -> StringUtils.isNotBlank(vo.getOrderId())) // 过滤无入库单号的无效行
.collect(Collectors.groupingBy(OutboundTemplateVO::getOrderId));
// 4. 遍历每个入库单分组处理
for (Map.Entry<String, List<OutboundTemplateVO>> entry : orderGroupMap.entrySet()) {
String orderId = entry.getKey();
List<OutboundTemplateVO> voList = entry.getValue();
OutboundOrderItems mainDO = null;
List<InboundOrderItems> itemDOList = new ArrayList<>();
try {
// 4.1 处理主表(每个入库单号只处理一次主表)
OutboundTemplateVO firstVO = voList.get(0); // 取第一条VO的主表信息
// 检查入库单是否已存在
OutboundOrderItems existMain = outboundOrderItemsMapper.selectOutboundOrderItemsById(orderId);
if (existMain != null) {
if (!isUpdateSupport) {
// 不支持更新,跳过该入库单
totalMainFailure++;
failureMsg.append(String.format("入库单号【%s】已存在,且不支持更新,跳过导入;\n", orderId));
totalItemFailure += voList.size(); // 该单的明细全部失败
continue;
}
// 支持更新,复用已有主表ID
mainDO = existMain;
// 复制VO中的主表字段到已有主表(只更新可修改的字段)
BeanUtils.copyProperties(firstVO, mainDO, "id", "createBy", "createTime"); // 排除不可更新字段
mainDO.setUpdateBy(operId);
mainDO.setUpdateTime(now);
mainDO.setUpdateUserCode(operId);
// 更新主表
outboundOrderItemsMapper.updateOutboundOrderItems(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已更新;\n", orderId));
} else {
// 新增主表
mainDO = new OutboundOrderItems();
// 复制主表字段(只复制主表相关字段,避免物料字段污染)
BeanUtils.copyProperties(firstVO, mainDO,
"sapNo", "materialName", "plannedQuantity", "actualQuantity",
"plannedPackages", "materialUnit", "materialRemark"); // 排除子表字段
// 填充主表必填字段
mainDO.setId(UUID.randomUUID().toString());
mainDO.setOrderId(orderId);
mainDO.setCreateBy(operId);
mainDO.setCreateTime(now);
mainDO.setCreateUserCode(operId);
mainDO.setUpdateBy(operId);
mainDO.setUpdateTime(now);
mainDO.setUpdateUserCode(operId);
// 设置默认值
if (mainDO.getSortNo() == null) {
mainDO.setSortNo(0L);
}
if (mainDO.getItemStatus() == null) {
mainDO.setItemStatus(1L); // 默认草稿状态
}
// 插入主表
outboundOrderItemsMapper.insertOutboundOrderItems(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已新增;\n", orderId));
}
// 4.2 处理子表明细(每条VO对应一条明细)
for (OutboundTemplateVO vo : voList) {
InboundOrderItems itemDO = new InboundOrderItems();
// 复制子表字段(物料相关)
BeanUtils.copyProperties(vo, itemDO,
"orderId", "systemNo", "orderTypeId", "batchId"); // 排除主表字段
// 填充明细必填字段
itemDO.setId(UUID.randomUUID().toString());
Materials materials = new Materials();
materials.setSapNo(vo.getSapNo());
itemDO.setMaterialId(vo.getSapNo());
itemDO.setOrderId(orderId); // 关联入库单号
itemDO.setBatchId(mainDO.getBatchCode());
itemDO.setInboundOrderId(mainDO.getId()); // 关联主表ID(核心!)
itemDO.setCreateBy(operId);
itemDO.setCreateTime(now);
itemDO.setCreateUserCode(operId);
itemDO.setSortNo(0L);
// 校验物料字段(示例:必填sapNo)
if (StringUtils.isBlank(vo.getSapNo())) {
throw new ServiceException(String.format("入库单号【%s】的物料SAP号为空,明细导入失败", orderId));
}
System.out.println(itemDO);
itemDOList.add(itemDO);
}
// 4.3 批量插入明细
if (!CollectionUtils.isEmpty(itemDOList)) {
int itemSuccess = outboundOrderItemsMapper.batchInsertOutboundOrderItems(itemDOList);
totalItemSuccess += itemSuccess;
totalItemFailure += (itemDOList.size() - itemSuccess);
successMsg.append(String.format("入库单号【%s】成功导入%d条物料明细;\n", orderId, itemSuccess));
if (itemDOList.size() - itemSuccess > 0) {
failureMsg.append(String.format("入库单号【%s】有%d条物料明细导入失败;\n", orderId, itemDOList.size() - itemSuccess));
}
}
} catch (Exception e) {
// 单个入库单处理失败,统计错误
totalMainFailure++;
totalItemFailure += voList.size();
failureMsg.append(String.format("入库单号【%s】处理失败:%s;\n", orderId, e.getMessage()));
}
}
// 5. 结果汇总
if (totalMainFailure > 0 || totalItemFailure > 0) {
// 有失败数据,抛出异常提示
String finalFailureMsg = String.format(
"导入结果:成功新增/更新%d个入库单,失败%d个;成功导入%d条明细,失败%d条。失败详情:%s",
totalMainSuccess, totalMainFailure, totalItemSuccess, totalItemFailure, failureMsg.toString()
);
throw new ServiceException(finalFailureMsg);
} else {
// 全部成功
String finalSuccessMsg = String.format(
"恭喜您,数据已全部导入成功!共处理%d个入库单,成功导入%d条物料明细。详情:%s",
totalMainSuccess, totalItemSuccess, successMsg.toString()
);
return finalSuccessMsg;
}
}
}
package com.ruoyi.inventory.service.impl;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import com.ruoyi.common.annotation.SerialExecution;
import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.OutboundOrderLog;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.inventory.domain.*;
import com.ruoyi.inventory.domain.vo.OutboundTemplateVO;
import com.ruoyi.inventory.mapper.InventoryMapper;
import com.ruoyi.inventory.mapper.OutboundOrderItemsMapper;
import com.ruoyi.inventory.mapper.OutboundOrderLogMapper;
......@@ -13,16 +17,14 @@ import org.apache.commons.lang3.SystemUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.inventory.domain.OutboundOrderItems;
import com.ruoyi.inventory.mapper.OutboundOrdersMapper;
import com.ruoyi.inventory.domain.OutboundOrders;
import com.ruoyi.inventory.service.IOutboundOrdersService;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;
/**
* 出库单主Service业务层处理
......@@ -48,6 +50,10 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
private WarehousesServiceImpl warehousesService;
@Autowired
private InventoryServiceImpl inventoryService;
@Autowired
private MaterialsServiceImpl materialsService;
@Autowired
private StorageLocationsServiceImpl storageLocationsService;
/**
* 查询出库单主
*
......@@ -244,4 +250,312 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName) {
// 1. 基础空值校验(完全保留你的代码)
if (CollectionUtils.isEmpty(inboundOrdersList)) {
throw new ServiceException("导入数据不能为空!");
}
// 2. 初始化变量(完全保留你的代码)
int totalMainSuccess = 0;
int totalMainFailure = 0;
int totalItemSuccess = 0;
int totalItemFailure = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
Date now = DateUtils.getNowDate();
Long userId = SecurityUtils.getUserId();
String operId = userId != null ? userId.toString() : "system";
Map<String, OutboundOrders> validMainMap = new HashMap<>();
Map<String, List<OutboundOrderItems>> validItemMap = new HashMap<>();
boolean hasValidateError = false;
// 3. 按入库单号分组(完全保留你的代码)
Map<String, List<OutboundTemplateVO>> orderGroupMap = inboundOrdersList.stream()
.filter(vo -> StringUtils.isNotBlank(vo.getOrderId()))
.collect(Collectors.groupingBy(OutboundTemplateVO::getOrderId));
// 4. 第一步:仅验证所有数据(完全保留你的代码)
for (Map.Entry<String, List<OutboundTemplateVO>> entry : orderGroupMap.entrySet()) {
String orderId = entry.getKey();
List<OutboundTemplateVO> voList = entry.getValue();
OutboundOrders mainDO = null;
List<OutboundOrderItems> itemDOList = new ArrayList<>();
try {
OutboundTemplateVO firstVO = voList.get(0);
OutboundOrders outboundOrdersQuery = new OutboundOrders();
outboundOrdersQuery.setOrderId(orderId);
List<OutboundOrders> existMains = outboundOrdersMapper.selectOutboundOrdersList(outboundOrdersQuery);
if (CollectionUtils.isEmpty(existMains) && existMains.size() > 1) {
throw new ServiceException(String.format("入库单号【%s】存在多条重复主表数据", orderId));
}
OutboundOrders existMain = CollectionUtils.isEmpty(existMains) ? null : existMains.get(0);
if (existMain != null) {
if (!Boolean.TRUE.equals(isUpdateSupport)) {
throw new ServiceException(String.format("入库单号【%s】已存在,且不支持更新", orderId));
}
mainDO = existMain;
BeanUtils.copyProperties(firstVO, mainDO, "id", "createBy", "createTime");
mainDO.setUpdateBy(operId);
mainDO.setUpdateTime(now);
mainDO.setUpdateUserCode(operId);
} else {
mainDO = new OutboundOrders();
com.ruoyi.common.utils.bean.BeanUtils.copyProperties(firstVO, mainDO,
"sapNo", "materialName", "plannedQuantity", "actualQuantity",
"plannedPackages", "materialUnit", "materialRemark");
if (StringUtils.isNotBlank(firstVO.getOwnerName())) {
Owners ownerQuery = new Owners();
ownerQuery.setOwnerName(firstVO.getOwnerName());
List<Owners> owners = ownersService.selectOwnersList(ownerQuery);
if (CollectionUtils.isEmpty(owners)) {
throw new ServiceException(String.format("业主【%s】不存在,无法新增入库单【%s】",
firstVO.getOwnerName(), orderId));
}
if (firstVO.getOwnerId() != null) {
boolean isMatch = owners.stream().anyMatch(o -> firstVO.getOwnerId().equals(o.getId()));
if (!isMatch) {
throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】与业主名称【%s】不匹配",
orderId, firstVO.getOwnerId(), firstVO.getOwnerName()));
}
mainDO.setOwnerId(firstVO.getOwnerId());
} else {
mainDO.setOwnerId(owners.get(0).getId());
}
} else if (firstVO.getOwnerId() != null) {
Owners ownerById = ownersService.selectOwnersById(firstVO.getOwnerId());
if (ownerById == null) {
throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】不存在",
orderId, firstVO.getOwnerId()));
}
mainDO.setOwnerId(firstVO.getOwnerId());
} else {
throw new ServiceException(String.format("入库单号【%s】的业主名称/ID不能为空", orderId));
}
mainDO.setId(UUID.randomUUID().toString());
mainDO.setOrderId(orderId);
mainDO.setOrderStatus(3L);
mainDO.setCreateBy(operId);
mainDO.setCreateTime(now);
mainDO.setCreateUserCode(operId);
mainDO.setUpdateBy(operId);
mainDO.setUpdateTime(now);
mainDO.setUpdateUserCode(operId);
mainDO.setSortNo(Optional.ofNullable(mainDO.getSortNo()).orElse(0L));
}
for (int i = 0; i < voList.size(); i++) {
OutboundTemplateVO vo = voList.get(i);
int lineNo = i + 1;
OutboundOrderItems itemDO = new OutboundOrderItems();
com.ruoyi.common.utils.bean.BeanUtils.copyProperties(vo, itemDO,
"orderId", "systemNo", "orderTypeId", "batchId");
itemDO.setId(UUID.randomUUID().toString());
itemDO.setOrderId(orderId);
itemDO.setBatchCode(Optional.ofNullable(mainDO.getBatchCode()).orElse(""));
itemDO.setInboundOrderId(mainDO.getId());
itemDO.setCreateBy(operId);
itemDO.setCreateTime(now);
itemDO.setCreateUserCode(operId);
itemDO.setSortNo(0L);
if (StringUtils.isBlank(vo.getSapNo())) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的物料SAP号不能为空",
orderId, lineNo));
}
Materials materialsQuery = new Materials();
materialsQuery.setSapNo(vo.getSapNo());
List<Materials> materialsList = materialsService.selectMaterialsList(materialsQuery);
if (CollectionUtils.isEmpty(materialsList)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的SAP号【%s】对应的物料不存在",
orderId, lineNo, vo.getSapNo()));
}
itemDO.setMaterialId(materialsList.get(0).getId());
if (StringUtils.isBlank(vo.getLocationName())) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位名称不能为空",
orderId, lineNo));
}
StorageLocations storageQuery = new StorageLocations();
storageQuery.setLocationCode(vo.getLocationName());
List<StorageLocations> storageList = storageLocationsService.selectStorageLocationsList(storageQuery);
if (CollectionUtils.isEmpty(storageList)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位【%s】不存在",
orderId, lineNo, vo.getLocationName()));
}
itemDO.setLocationId(storageList.get(0).getId());
List<Warehouses> warehousesList = warehousesService.selectWarehousesList(new Warehouses());
if (CollectionUtils.isEmpty(warehousesList)) {
throw new ServiceException(String.format("系统未配置仓库,无法导入入库单号【%s】的第%d条明细",
orderId, lineNo));
}
itemDO.setWarehouseId(warehousesList.get(0).getId());
Inventory itemsList = new Inventory();
itemsList.setWarehousesId(itemDO.getWarehouseId());
itemsList.setMaterialId(itemDO.getMaterialId());
itemsList.setLocationId(itemDO.getLocationId());
List<Inventory> inventory = inventoryService.selectInventoryList(itemsList);
if (CollectionUtils.isEmpty(inventory)) {
throw new ServiceException(String.format(
"入库单号【%s】第%d条明细:仓库【%s】+物料【%s】+库位【%s】组合的库存记录不存在",
orderId, lineNo, itemDO.getWarehouseName(),firstVO.getMaterialName(), firstVO.getLocationName()));
}
itemDO.setInventoryId(inventory.get(0).getId());
itemDO.setItemStatus(3l);
itemDOList.add(itemDO);
}
validMainMap.put(orderId, mainDO);
validItemMap.put(orderId, itemDOList);
} catch (Exception e) {
hasValidateError = true;
totalMainFailure++;
totalItemFailure += voList.size();
failureMsg.append(String.format("入库单号【%s】验证失败:%s;\n", orderId, e.getMessage()));
}
}
// 5. 有验证失败直接抛异常(完全保留你的代码)
if (hasValidateError) {
throw new ServiceException(String.format("验证失败,导入终止!失败详情:%s", failureMsg.toString()));
}
// 6. 验证全通过:统一执行入库/更新操作(完全保留你的代码)
for (Map.Entry<String, OutboundOrders> entry : validMainMap.entrySet()) {
String orderId = entry.getKey();
OutboundOrders mainDO = entry.getValue();
List<OutboundOrderItems> itemDOList = validItemMap.get(orderId);
if (mainDO != null) {
outboundOrdersMapper.insertOutboundOrders(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已新增;\n", orderId));
} else {
outboundOrdersMapper.updateOutboundOrders(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已更新;\n", orderId));
}
if (!CollectionUtils.isEmpty(itemDOList)) {
int itemSuccess = outboundOrderItemsMapper.batchInsertOutboundOrderItems(itemDOList);
totalItemSuccess += itemSuccess;
int itemFail = itemDOList.size() - itemSuccess;
totalItemFailure += itemFail;
successMsg.append(String.format("入库单号【%s】成功导入%d条物料明细;\n", orderId, itemSuccess));
if (itemFail > 0) {
failureMsg.append(String.format("入库单号【%s】有%d条物料明细导入失败;\n", orderId, itemFail));
}
}
}
// ========== 仅新增这一段代码(核心:事务提交后执行自定义逻辑) ==========
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 保存当前需要的变量,用于事务提交后执行
Map<String, OutboundOrders> finalValidMainMap = new HashMap<>(validMainMap);
Map<String, List<OutboundOrderItems>> finalValidItemMap = new HashMap<>(validItemMap);
String finalOperId = operId;
Date finalNow = now;
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务提交后,调用你原来的executeCustomLogic方法
executeCustomLogic(finalValidMainMap, finalValidItemMap, finalOperId, finalNow);
}
});
} else {
// 无事务时,直接执行(和你原有逻辑一致)
executeCustomLogic(validMainMap, validItemMap, operId, now);
}
// ========== 新增代码结束 ==========
// 8. 结果汇总(完全保留你的代码)
if (totalMainFailure > 0 || totalItemFailure > 0) {
String finalFailureMsg = String.format(
"导入结果:成功新增/更新%d个入库单,失败%d个;成功导入%d条明细,失败%d条。失败详情:%s",
totalMainSuccess, totalMainFailure, totalItemSuccess, totalItemFailure, failureMsg.toString()
);
throw new ServiceException(finalFailureMsg);
} else {
String finalSuccessMsg = String.format(
"恭喜您,数据已全部导入成功!共处理%d个入库单,成功导入%d条物料明细。详情:%s",
totalMainSuccess, totalItemSuccess, successMsg.toString()
);
return finalSuccessMsg;
}
}
// 仅修改这个方法中【设置日志ID】的一行代码,其余完全保留
private void executeCustomLogic(Map<String, OutboundOrders> validMainMap,
Map<String, List<OutboundOrderItems>> validItemMap,
String operId, Date now) {
for (String orderId : validMainMap.keySet()) {
OutboundOrders mainDO = validMainMap.get(orderId);
List<OutboundOrderItems> itemList = validItemMap.get(orderId);
System.out.println(String.format("订单【%s】导入成功,主表ID:%s,明细数:%d",
orderId, mainDO.getId(), itemList.size()));
List<OutboundOrderLog> outboundOrderLogs = new ArrayList<>();
for (OutboundOrderItems item : itemList) {
OutboundOrderLog outboundOrderLog = new OutboundOrderLog();
// ========== 唯一改动:设置日志ID = 明细ID ==========
outboundOrderLog.setId(item.getId());
outboundOrderLog.setOrderId(item.getOutboundOrderId());
BeanUtils.copyProperties(item, outboundOrderLog);
outboundOrderLogs.add(outboundOrderLog);
}
outboundOrderLogMapper.batchOutboundOrderLog(outboundOrderLogs);
ship(itemList);
}
}
public int ship(List<OutboundOrderItems> outboundOrderItems)
{
if (!outboundOrderItems.isEmpty()) {
List<String> inventoryIds = new ArrayList<>(); // 手动收集inventoryId
for (OutboundOrderItems outboundOrderItem : outboundOrderItems) {
// 直接用明细的inventoryId,不查日志!
String inventoryId = outboundOrderItem.getInventoryId();
if (StringUtils.isBlank(inventoryId)) {
throw new ServiceException("明细ID【" + outboundOrderItem.getId() + "】的库存ID为空,无法扣减");
}
Inventory inventory = inventoryService.selectInventoryById(inventoryId);
if (inventory == null) {
throw new ServiceException("库存ID【" + inventoryId + "】不存在,无法扣减");
}
// 扣减库存
inventory.setQuantity(inventory.getQuantity() - outboundOrderItem.getActualQuantity());
if (inventory.getQuantity() == 0) {
inventory.setInventoryStatus(0L);
}
inventoryService.updateInventory(inventory);
inventoryIds.add(inventoryId); // 收集库存ID用于刷新
}
inventoryService.RefreshInventory(inventoryIds);
}
return 1;
}
}
package com.ruoyi.inventory.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.inventory.domain.vo.OwnerTemplateVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.inventory.mapper.OwnersMapper;
......@@ -21,76 +26,69 @@ import com.ruoyi.inventory.service.IOwnersService;
* @date 2025-11-28
*/
@Service
public class OwnersServiceImpl implements IOwnersService
{
public class OwnersServiceImpl implements IOwnersService {
@Autowired
private OwnersMapper ownersMapper;
/**
* 查询货主信息
*
*
* @param id 货主信息主键
* @return 货主信息
*/
@Override
public Owners selectOwnersById(String id)
{
public Owners selectOwnersById(String id) {
return ownersMapper.selectOwnersById(id);
}
/**
* 查询货主信息列表
*
*
* @param owners 货主信息
* @return 货主信息
*/
@Override
public List<Owners> selectOwnersList(Owners owners)
{
public List<Owners> selectOwnersList(Owners owners) {
return ownersMapper.selectOwnersList(owners);
}
/**
* 新增货主信息
*
*
* @param owners 货主信息
* @return 结果
*/
@Override
public int insertOwners(Owners owners)
{
public int insertOwners(Owners owners) {
Long userId = SecurityUtils.getUserId();
String operId = userId.toString();
Date now = DateUtils.getNowDate();
// 填充创建人、创建时间、修改人、修改时间
owners.setId(UUID.randomUUID().toString());
owners.setCreateBy(operId);
owners.setCreateTime(now);
// 填充创建用户编码和更新用户编码
owners.setCreateUserCode(operId);
// 设置默认值
if (owners.getIsActive() == null)
{
if (owners.getIsActive() == null) {
owners.setIsActive(1L); // 默认激活
}
if (owners.getIsUsed() == null)
{
owners.setIsUsed(0L); // 默认未删除
if (owners.getIsUsed() == null) {
owners.setIsUsed(1L); // 默认未删除
}
if (owners.getSortNo() == null)
{
if (owners.getSortNo() == null) {
owners.setSortNo(0L); // 默认排序号
}
return ownersMapper.insertOwners(owners);
}
@Override
public String importOwners(List<Owners> ownersList, Boolean isUpdateSupport, String operName)
{
if (StringUtils.isNull(ownersList) || ownersList.size() == 0)
{
public String importOwners(List<OwnerTemplateVO> ownersList, Boolean isUpdateSupport, String operName) {
if (CollectionUtils.isEmpty(ownersList)) {
throw new ServiceException("导入用户数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
......@@ -99,48 +97,73 @@ public class OwnersServiceImpl implements IOwnersService
// 获取当前登录用户ID
Long userId = SecurityUtils.getUserId();
String operId = userId.toString();
for (Owners owners : ownersList)
{
try
{
// 批量插入的有效数据集合
List<Owners> batchInsertList = new ArrayList<>();
for (OwnerTemplateVO ownerTemp : ownersList) {
try {
Owners owners = new Owners();
// 处理激活状态转换
BeanUtils.copyProperties(ownerTemp, owners);
if (ownerTemp.getIsActive()!=null) {
owners.setIsActive(Long.valueOf(ownerTemp.getIsActive()));
}
// 类型转换
if (ownerTemp.getOwnerType()!=null) {
owners.setOwnerType(Long.valueOf(ownerTemp.getOwnerType()));
}
// 生成UUID主键
owners.setId(UUID.randomUUID().toString());
// 填充创建人、创建时间、修改人、修改时间
// 填充公共字段
owners.setCreateBy(operId);
owners.setCreateTime(now);
// 填充创建用户编码和更新用户编码
owners.setCreateUserCode(operId);
// 设置默认值
if (owners.getIsActive() == null)
{
if (owners.getIsActive() == null) {
owners.setIsActive(1L); // 默认激活
}
if (owners.getIsUsed() == null)
{
owners.setIsUsed(0L); // 默认未删除
if (owners.getIsUsed() == null) {
owners.setIsUsed(1L); // 默认未删除
}
if (owners.getSortNo() == null)
{
if (owners.getSortNo() == null) {
owners.setSortNo(0L); // 默认排序号
}
ownersMapper.insertOwners(owners);
// 加入批量集合
batchInsertList.add(owners);
successNum++;
successMsg.append("<br/>" + successNum + "、用户 " + owners.getOwnerName() + " 导入成功");
}
catch (Exception e)
{
} catch (Exception e) {
failureNum++;
String msg = "<br/>" + failureNum + "、账号 " + owners.getOwnerName() + " 导入失败:";
String ownerName = ownerTemp.getOwnerCode() != null ? ownerTemp.getOwnerCode() : "未知名称";
String msg = "<br/>" + failureNum + "、账号 " + ownerName + " 导入失败:";
failureMsg.append(msg + e.getMessage());
// 异常数据不加入批量集合,继续处理下一条
continue;
}
}
// 批量插入有效数据(如果有)
if (!CollectionUtils.isEmpty(batchInsertList)) {
try {
ownersMapper.batchInsertOwners(batchInsertList);
} catch (Exception e) {
// 批量插入失败时,统计失败数量并抛出异常
failureNum += batchInsertList.size();
successNum -= batchInsertList.size();
failureMsg.insert(0, String.format("<br/>批量插入失败:%s,已失败数据条数追加 %d 条",
e.getMessage(), batchInsertList.size()));
}
}
if (failureNum > 0)
{
// 处理结果反馈
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确");
throw new ServiceException(failureMsg.toString());
}
else
{
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
......@@ -188,4 +211,5 @@ public class OwnersServiceImpl implements IOwnersService
{
return ownersMapper.deleteOwnersById(id);
}
}
package com.ruoyi.inventory.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.inventory.domain.Owners;
import com.ruoyi.inventory.domain.StorageLocationsCategory;
import com.ruoyi.inventory.domain.vo.StorageLocationsLocationTemplateVO;
import com.ruoyi.inventory.mapper.MaterialsMapper;
import com.ruoyi.inventory.mapper.StorageLocationsCategoryMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.inventory.mapper.StorageLocationsMapper;
......@@ -222,4 +229,91 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
List<StorageLocations> storageLocations1 =storageLocationsMapper.getStorageLocationsList(storageLocations);
return storageLocations1;
}
@Override
public String importStorageLocationsLocation(List<StorageLocationsLocationTemplateVO> storageLocationsLocationTemplateVOS,
Boolean isUpdateSupport,
String operName) {
// 空数据校验
if (CollectionUtils.isEmpty(storageLocationsLocationTemplateVOS)) {
throw new ServiceException("导入库位数据不能为空!");
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
Date now = DateUtils.getNowDate();
// 获取当前登录用户ID
Long userId = SecurityUtils.getUserId();
String operId = userId.toString();
// 批量插入数据集合
List<StorageLocations> batchInsertList = new ArrayList<>();
for (StorageLocationsLocationTemplateVO templateVO : storageLocationsLocationTemplateVOS) {
try {
StorageLocations storageLocations = new StorageLocations();
// 拷贝基础属性
BeanUtils.copyProperties(templateVO, storageLocations);
// 字段类型转换与赋值
storageLocations.setId(UUID.randomUUID().toString());
if (StringUtils.isNotBlank(templateVO.getLocationUsage())) {
storageLocations.setLocationUsage(Integer.valueOf(templateVO.getLocationUsage()));
}
if (StringUtils.isNotBlank(templateVO.getIsEnabled())) {
storageLocations.setIsEnabled(Long.valueOf(templateVO.getIsEnabled()));
}
// 填充公共字段
storageLocations.setCreateBy(operId);
storageLocations.setCreateTime(now);
storageLocations.setCreateUserCode(operId);
// 设置默认值
if (storageLocations.getIsUsed() == null) {
storageLocations.setIsUsed(1L); // 默认未删除
}
if (storageLocations.getSortNo() == null) {
storageLocations.setSortNo(0L); // 默认排序号
}
// 加入批量集合
batchInsertList.add(storageLocations);
successNum++;
String locationName = storageLocations.getLocationName() != null ? storageLocations.getLocationName() : "未知名称";
successMsg.append("<br/>" + successNum + "、库位 " + locationName + " 导入成功");
} catch (Exception e) {
failureNum++;
String locationName = templateVO.getLocationCode() != null ? templateVO.getLocationCode() : "未知名称";
String msg = "<br/>" + failureNum + "、库位 " + locationName + " 导入失败:";
failureMsg.append(msg + e.getMessage());
// 异常数据跳过,继续处理下一条
continue;
}
}
// 执行批量插入(有有效数据时)
if (!CollectionUtils.isEmpty(batchInsertList)) {
try {
storageLocationsMapper.batchInsertStorageLocations(batchInsertList);
} catch (Exception e) {
// 批量插入失败,更新失败统计
failureNum += batchInsertList.size();
successNum -= batchInsertList.size();
failureMsg.insert(0, String.format("<br/>批量插入失败:%s,失败条数追加 %d 条",
e.getMessage(), batchInsertList.size()));
}
}
// 结果反馈处理
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
}
......@@ -9,9 +9,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="inventoryType" column="inventory_type" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id" />
<result property="materialName" column="material_name"/>
<result property="batchId" column="batch_id" />
<result property="warehousesCode" column="warehouses_code" />
<result property="warehousesCode" column="warehouses_code" />
<result property="warehousesName" column="warehouses_name"/>
<result property="locationId" column="location_id" />
<result property="locationName" column="location_name"/>
<result property="ownerId" column="owner_id" />
<result property="quantity" column="quantity" />
<result property="lockedQuantity" column="locked_quantity" />
......@@ -30,6 +33,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="warehousesId" column="warehouses_id" />
<result property="oderCode" column="order_code" />
</resultMap>
<resultMap type="com.ruoyi.inventory.domain.TO.StocktakeItemsTo" id="StocktakeItemsResult">
......@@ -212,14 +216,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id}
</select>
<select id="listByMaterialId" parameterType="String" resultMap="InventoryResult">
<include refid="selectInventoryVo"/>
where 1=1
SELECT
i.id,
i.inventory_type,
i.warehouses_id,
w.warehouses_name,
i.order_id,
i.material_id,
m.material_name,
i.batch_id,
i.location_id,
sl.location_name,
i.owner_id,
i.quantity,
i.locked_quantity,
i.unit_weight,
i.total_weight,
i.total_volume,
i.production_date,
i.expiration_date,
i.inventory_status,
i.last_inbound_time,
i.last_outbound_time,
i.is_used,
i.sort_no,
i.create_time,
i.create_user_code,
i.update_time,
i.update_user_code
FROM inventory i
LEFT JOIN materials m ON i.material_id = m.id AND m.is_used = 1
LEFT JOIN warehouses w ON i.warehouses_id = w.id AND w.is_enabled = 1 AND w.is_used = 1
LEFT JOIN storage_locations sl ON i.location_id = sl.id AND sl.is_enabled = 1 AND sl.is_used = 1
WHERE 1=1
<if test="materialId != null and materialId.trim() != ''">
and material_id = #{materialId}
AND i.material_id = #{materialId}
</if>
<![CDATA[
and inventory_status = '1'
]]>
AND i.inventory_status = '1'
]]>
ORDER BY i.expiration_date ASC
</select>
<insert id="insertInventory" parameterType="Inventory">
insert into inventory
......@@ -345,8 +381,8 @@ and inventory_status = '1'
sum(i.quantity) as value
from inventory i
left join materials m on i.material_id = m.id
where i.is_used = 1 and i.production_date &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and i.production_date &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
where i.is_used = 1 and i.last_inbound_time &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and i.last_inbound_time &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
group by m.material_name
order by sum(i.quantity) desc
</select>
......@@ -357,8 +393,8 @@ and inventory_status = '1'
sum(i.quantity)*i.unit_price as value
from inventory i
left join materials m on i.material_id = m.id
where i.is_used = 1 and i.production_date &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and i.production_date &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
where i.is_used = 1 and i.last_inbound_time &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and i.last_inbound_time &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
group by m.material_name
order by sum(i.quantity)*i.unit_price desc
</select>
......
......@@ -257,7 +257,7 @@
o.order_id as main_order_id
from outbound_order_items oi
left join outbound_orders o on oi.outbound_order_id = o.id
left join materials m on oi.material_id = m.sap_no
left join materials m on oi.material_id = m.id
left join warehouses w on oi.warehouse_id = w.id
left join storage_locations sl on oi.location_id = sl.id
<where>
......
......@@ -9,6 +9,7 @@
<result property="orderId" column="order_id" />
<result property="systemNo" column="system_no" />
<result property="orderTypeId" column="order_type_id" />
<result property="orderType" column="order_type" /> <!-- 新增order_type字段映射 -->
<result property="batchCode" column="batch_code" />
<result property="warehouseId" column="warehouse_id" />
<result property="warehouseName" column="warehouse_name" />
......@@ -74,6 +75,7 @@
oo.order_id,
oo.system_no,
oo.order_type_id,
oo.order_type, -- 新增order_type字段查询
oo.batch_code,
oo.warehouse_id,
w.warehouses_name as warehouse_name,
......@@ -103,6 +105,7 @@
<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="orderType != null and orderType != ''"> and oo.order_type = #{orderType}</if> <!-- 新增order_type查询条件 -->
<if test="batchCode != null and batchCode != ''"> and oo.batch_code = #{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>
......@@ -123,9 +126,9 @@
oo.order_id,
oo.system_no,
oo.order_type_id,
oo.order_type, -- 新增order_type字段查询
oo.batch_code,
oo.warehouse_id,
w.warehouses_name as warehouse_name,
oo.owner_id,
o.owner_name,
oo.order_status,
......@@ -190,6 +193,7 @@
<if test="orderId != null">order_id,</if>
<if test="systemNo != null">system_no,</if>
<if test="orderTypeId != null">order_type_id,</if>
<if test="orderType != null">order_type,</if> <!-- 新增order_type字段插入 -->
<if test="batchCode != null">batch_code,</if>
<if test="warehouseId != null">warehouse_id,</if>
<if test="ownerId != null">owner_id,</if>
......@@ -212,6 +216,7 @@
<if test="orderId != null">#{orderId},</if>
<if test="systemNo != null">#{systemNo},</if>
<if test="orderTypeId != null">#{orderTypeId},</if>
<if test="orderType != null">#{orderType},</if> <!-- 新增order_type值插入 -->
<if test="batchCode != null">#{batchCode},</if>
<if test="warehouseId != null">#{warehouseId},</if>
<if test="ownerId != null">#{ownerId},</if>
......@@ -237,6 +242,7 @@
<if test="orderId != null">order_id = #{orderId},</if>
<if test="systemNo != null">system_no = #{systemNo},</if>
<if test="orderTypeId != null">order_type_id = #{orderTypeId},</if>
<if test="orderType != null">order_type = #{orderType},</if> <!-- 新增order_type字段更新 -->
<if test="batchCode != null">batch_code = #{batchCode},</if>
<if test="warehouseId != null">warehouse_id = #{warehouseId},</if>
<if test="ownerId != null">owner_id = #{ownerId},</if>
......@@ -303,7 +309,7 @@
m.material_name as name,
sum(ooi.actual_quantity) as value
from outbound_order_items ooi
left join materials m on ooi.material_id = m.sap_no
left join materials m on ooi.material_id = m.id
where ooi.is_used = 1 and ooi.shipped_at &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and ooi.shipped_at &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
group by m.material_name
......@@ -316,7 +322,7 @@
m.material_name as name,
sum(ooi.actual_quantity)*ooi.unit_price as value
from outbound_order_items ooi
left join materials m on ooi.material_id = m.sap_no
left join materials m on ooi.material_id = m.id
where ooi.is_used = 1 and ooi.shipped_at &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and ooi.shipped_at &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
group by m.material_name
......@@ -326,6 +332,6 @@
<select id="outboundOrdersCount" resultType="String">
select count(*) from outbound_order_items where is_used = 1 and shipped_at &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and shipped_at &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
and shipped_at &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.OwnersMapper">
<resultMap type="Owners" id="OwnersResult">
<result property="id" column="id" />
<result property="ownerCode" column="owner_code" />
......@@ -19,34 +19,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="sortNo" column="sort_no" />
<result property="createTime" column="create_time" />
<result property="createUserCode" column="create_user_code" />
<result property="englishName" column="english_name" />
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="isUsed" column="is_used" />
</resultMap>
<sql id="selectOwnersVo">
select id, owner_code, owner_name, owner_type, contact_person, contact_phone, email, address, tax_number, bank_account, is_active, sort_no, create_time, create_user_code, update_time, update_user_code, is_used from owners
select id, owner_code, owner_name, owner_type, english_name ,contact_person, contact_phone, email, address, tax_number, bank_account, is_active, sort_no, create_time, create_user_code, update_time, update_user_code, is_used from owners
</sql>
<select id="selectOwnersList" parameterType="Owners" resultMap="OwnersResult">
<include refid="selectOwnersVo"/>
where is_used = 0
<if test="ownerCode != null and ownerCode != ''"> and owner_code = #{ownerCode}</if>
<if test="ownerName != null and ownerName != ''"> and owner_name like concat('%', #{ownerName}, '%')</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="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>
<if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if>
order by sort_no asc
where is_used = 1
<if test="ownerCode != null and ownerCode != ''"> and owner_code = #{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="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>
<if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if>
order by sort_no asc
</select>
<select id="selectOwnersById" parameterType="String" resultMap="OwnersResult">
<include refid="selectOwnersVo"/>
where id = #{id}
......@@ -59,6 +63,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="ownerCode != null">owner_code,</if>
<if test="ownerName != null">owner_name,</if>
<if test="ownerType != null">owner_type,</if>
<!-- 新增english_name插入字段 -->
<if test="englishName != null">english_name,</if>
<if test="contactPerson != null">contact_person,</if>
<if test="contactPhone != null">contact_phone,</if>
<if test="email != null">email,</if>
......@@ -71,12 +77,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null">create_user_code,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateUserCode != null">update_user_code,</if>
</trim>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="ownerCode != null">#{ownerCode},</if>
<if test="ownerName != null">#{ownerName},</if>
<if test="ownerType != null">#{ownerType},</if>
<!-- 新增englishName插入值 -->
<if test="englishName != null">#{englishName},</if>
<if test="contactPerson != null">#{contactPerson},</if>
<if test="contactPhone != null">#{contactPhone},</if>
<if test="email != null">#{email},</if>
......@@ -89,7 +97,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null">#{createUserCode},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateUserCode != null">#{updateUserCode},</if>
</trim>
</trim>
</insert>
<!-- 新增批量插入方法 -->
<insert id="batchInsertOwners" parameterType="java.util.List">
insert into owners (
id, owner_code, owner_name, owner_type, english_name,
contact_person, contact_phone, email, address, tax_number,
bank_account, is_active, sort_no, create_time, create_user_code,
update_time, update_user_code, is_used
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.id}, #{item.ownerCode}, #{item.ownerName}, #{item.ownerType}, #{item.englishName},
#{item.contactPerson}, #{item.contactPhone}, #{item.email}, #{item.address}, #{item.taxNumber},
#{item.bankAccount}, #{item.isActive}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode},
#{item.updateTime}, #{item.updateUserCode}, #{item.isUsed}
)
</foreach>
</insert>
<update id="updateOwners" parameterType="Owners">
......@@ -98,6 +124,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="ownerCode != null">owner_code = #{ownerCode},</if>
<if test="ownerName != null">owner_name = #{ownerName},</if>
<if test="ownerType != null">owner_type = #{ownerType},</if>
<!-- 新增english_name更新字段 -->
<if test="englishName != null">english_name = #{englishName},</if>
<if test="contactPerson != null">contact_person = #{contactPerson},</if>
<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
<if test="email != null">email = #{email},</if>
......@@ -120,7 +148,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update>
<update id="deleteOwnersByIds" parameterType="String">
update owners set is_used = 1 where id in
update owners set is_used = 1 where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
......
......@@ -4,7 +4,7 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.StorageLocationsMapper">
<!-- 原有基础ResultMap -->
<!-- 原有基础ResultMap - 仅添加新字段映射 -->
<resultMap type="StorageLocations" id="StorageLocationsResult">
<result property="id" column="id" />
<result property="locationCode" column="location_code" />
......@@ -28,9 +28,18 @@
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="warehousesId" column="warehouses_id" />
<!-- 新增字段映射 -->
<result property="putawayOrder" column="putaway_order" />
<result property="pickingOrder" column="picking_order" />
<result property="LocationUsage" column="location_usage" />
<result property="locationHandling" column="location_handling" />
<result property="turnoverDemand" column="turnover_demand" />
<result property="pickingArea" column="picking_area" />
<result property="allowMixedProducts" column="allow_mixed_products" />
<result property="allowMixedBatches" column="allow_mixed_batches" />
</resultMap>
<!-- 关联仓库表的ResultMap -->
<!-- 关联仓库表的ResultMap - 继承基础ResultMap(自动包含新字段) -->
<resultMap type="StorageLocations" id="StorageLocationsWithWarehousesResult" extends="StorageLocationsResult">
<result property="warehousesName" column="warehouses_name"/>
<result property="warehousesAddress" column="warehouses_address"/>
......@@ -44,7 +53,11 @@
sl.zone_code, sl.row_code, sl.column_code, sl.layer_code, sl.capacity,
sl.volume_capacity, sl.allowed_hazard_levels, sl.allowed_category_ids,
sl.temperature_zone, sl.is_enabled, sl.is_used, sl.sort_no,
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id,
-- 新增字段查询
sl.putaway_order, sl.picking_order, sl.location_usage,
sl.location_handling, sl.turnover_demand, sl.picking_area,
sl.allow_mixed_products, sl.allow_mixed_batches
from storage_locations sl
where sl.is_used = 1
</sql>
......@@ -56,6 +69,10 @@
sl.volume_capacity, sl.allowed_hazard_levels, sl.allowed_category_ids,
sl.temperature_zone, sl.is_enabled, sl.is_used, sl.sort_no,
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id,
-- 新增字段查询
sl.putaway_order, sl.picking_order, sl.location_usage,
sl.location_handling, sl.turnover_demand, sl.picking_area,
sl.allow_mixed_products, sl.allow_mixed_batches,
w.warehouses_name
from storage_locations sl
left join warehouses w on sl.warehouses_id = w.id
......@@ -82,6 +99,15 @@
<if test="sortNo != null "> and sl.sort_no = #{sortNo}</if>
<if test="createUserCode != null and createUserCode != ''"> and sl.create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and sl.update_user_code = #{updateUserCode}</if>
<!-- 新增字段查询条件 -->
<if test="putawayOrder != null "> and sl.putaway_order = #{putawayOrder}</if>
<if test="pickingOrder != null "> and sl.picking_order = #{pickingOrder}</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="turnoverDemand != null and turnoverDemand != ''"> and sl.turnover_demand = #{turnoverDemand}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
</select>
<!-- 关联仓库表的列表查询(简化) -->
......@@ -94,6 +120,15 @@
<if test="zoneCode != null and zoneCode != ''"> and sl.zone_code = #{zoneCode}</if>
<if test="warehousesName != null and warehousesName != ''"> and w.warehouses_name like concat('%', #{warehousesName}, '%')</if>
<if test="warehousesManager != null and warehousesManager != ''"> and w.warehouses_manager = #{warehousesManager}</if>
<!-- 新增字段查询条件 -->
<if test="putawayOrder != null "> and sl.putaway_order = #{putawayOrder}</if>
<if test="pickingOrder != null "> and sl.picking_order = #{pickingOrder}</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="turnoverDemand != null and turnoverDemand != ''"> and sl.turnover_demand = #{turnoverDemand}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
</select>
<!-- 根据ID查询(调整:保留where,单独条件) -->
......@@ -102,7 +137,11 @@
sl.zone_code, sl.row_code, sl.column_code, sl.layer_code, sl.capacity,
sl.volume_capacity, sl.allowed_hazard_levels, sl.allowed_category_ids,
sl.temperature_zone, sl.is_enabled, sl.is_used, sl.sort_no,
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id,
-- 新增字段查询
sl.putaway_order, sl.picking_order, sl.location_usage,
sl.location_handling, sl.turnover_demand, sl.picking_area,
sl.allow_mixed_products, sl.allow_mixed_batches
from storage_locations sl
where sl.id = #{id}
</select>
......@@ -114,6 +153,10 @@
sl.volume_capacity, sl.allowed_hazard_levels, sl.allowed_category_ids,
sl.temperature_zone, sl.is_enabled, sl.is_used, sl.sort_no,
sl.create_time, sl.create_user_code, sl.update_time, sl.update_user_code, sl.warehouses_id,
-- 新增字段查询
sl.putaway_order, sl.picking_order, sl.location_usage,
sl.location_handling, sl.turnover_demand, sl.picking_area,
sl.allow_mixed_products, sl.allow_mixed_batches,
w.warehouses_name, w.warehouses_address, w.warehouses_manager, w.warehouses_phone
from storage_locations sl
left join warehouses w on sl.warehouses_code = w.warehouses_code
......@@ -165,7 +208,7 @@
<if test="warehousesCode != null and warehousesCode != ''"> and sl.warehouses_code = #{warehousesCode}</if>
</select>
<!-- 原有新增/更新/删除方法(无修改) -->
<!-- 原有新增/更新/删除方法(仅添加新字段) -->
<insert id="insertStorageLocations" parameterType="StorageLocations">
insert into storage_locations
<trim prefix="(" suffix=")" suffixOverrides=",">
......@@ -191,6 +234,15 @@
<if test="updateTime != null">update_time,</if>
<if test="updateUserCode != null">update_user_code,</if>
<if test="warehousesId != null">warehouses_id,</if>
<!-- 新增字段插入 -->
<if test="putawayOrder != null">putaway_order,</if>
<if test="pickingOrder != null">picking_order,</if>
<if test="LocationUsage != null">location_usage,</if>
<if test="locationHandling != null">location_handling,</if>
<if test="turnoverDemand != null">turnover_demand,</if>
<if test="pickingArea != null">picking_area,</if>
<if test="allowMixedProducts != null">allow_mixed_products,</if>
<if test="allowMixedBatches != null">allow_mixed_batches,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
......@@ -215,9 +267,42 @@
<if test="updateTime != null">#{updateTime},</if>
<if test="updateUserCode != null">#{updateUserCode},</if>
<if test="warehousesId != null">#{warehousesId},</if>
<!-- 新增字段值 -->
<if test="putawayOrder != null">#{putawayOrder},</if>
<if test="pickingOrder != null">#{pickingOrder},</if>
<if test="LocationUsage != null">#{LocationUsage},</if>
<if test="locationHandling != null">#{locationHandling},</if>
<if test="turnoverDemand != null">#{turnoverDemand},</if>
<if test="pickingArea != null">#{pickingArea},</if>
<if test="allowMixedProducts != null">#{allowMixedProducts},</if>
<if test="allowMixedBatches != null">#{allowMixedBatches},</if>
</trim>
</insert>
<!-- 新增批量插入库位信息方法 -->
<insert id="batchInsertStorageLocations" parameterType="java.util.List">
insert into storage_locations (
id, location_code, location_name, warehouses_code, location_type,
zone_code, row_code, column_code, layer_code, capacity,
volume_capacity, allowed_hazard_levels, allowed_category_ids, temperature_zone,
is_enabled, is_used, sort_no, create_time, create_user_code,
update_time, update_user_code, warehouses_id, putaway_order, picking_order,
location_usage, location_handling, turnover_demand, picking_area,
allow_mixed_products, allow_mixed_batches
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.id}, #{item.locationCode}, #{item.locationName}, #{item.warehousesCode}, #{item.locationType},
#{item.zoneCode}, #{item.rowCode}, #{item.columnCode}, #{item.layerCode}, #{item.capacity},
#{item.volumeCapacity}, #{item.allowedHazardLevels}, #{item.allowedCategoryIds}, #{item.temperatureZone},
#{item.isEnabled}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode},
#{item.updateTime}, #{item.updateUserCode}, #{item.warehousesId}, #{item.putawayOrder}, #{item.pickingOrder},
#{item.LocationUsage}, #{item.locationHandling}, #{item.turnoverDemand}, #{item.pickingArea},
#{item.allowMixedProducts}, #{item.allowMixedBatches}
)
</foreach>
</insert>
<update id="updateStorageLocations" parameterType="StorageLocations">
update storage_locations
<trim prefix="SET" suffixOverrides=",">
......@@ -241,6 +326,15 @@
<if test="createUserCode != null">create_user_code = #{createUserCode},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUserCode != null">update_user_code = #{updateUserCode},</if>
<!-- 新增字段更新 -->
<if test="putawayOrder != null">putaway_order = #{putawayOrder},</if>
<if test="pickingOrder != null">picking_order = #{pickingOrder},</if>
<if test="LocationUsage != null">location_usage = #{LocationUsage},</if>
<if test="locationHandling != null">location_handling = #{locationHandling},</if>
<if test="turnoverDemand != null">turnover_demand = #{turnoverDemand},</if>
<if test="pickingArea != null">picking_area = #{pickingArea},</if>
<if test="allowMixedProducts != null">allow_mixed_products = #{allowMixedProducts},</if>
<if test="allowMixedBatches != null">allow_mixed_batches = #{allowMixedBatches},</if>
</trim>
where id = #{id}
</update>
......@@ -277,6 +371,15 @@
<if test="sortNo != null "> and sl.sort_no = #{sortNo}</if>
<if test="createUserCode != null and createUserCode != ''"> and sl.create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and sl.update_user_code = #{updateUserCode}</if>
<!-- 新增字段查询条件 -->
<if test="putawayOrder != null "> and sl.putaway_order = #{putawayOrder}</if>
<if test="pickingOrder != null "> and sl.picking_order = #{pickingOrder}</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="turnoverDemand != null and turnoverDemand != ''"> and sl.turnover_demand = #{turnoverDemand}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
</select>
<!-- 关联仓库的getStorageLocationsList -->
......@@ -289,6 +392,15 @@
<if test="locationType != null "> and sl.location_type = #{locationType}</if>
<if test="zoneCode != null and zoneCode != ''"> and sl.zone_code = #{zoneCode}</if>
<if test="warehousesName != null and warehousesName != ''"> and w.warehouses_name like concat('%', #{warehousesName}, '%')</if>
<!-- 新增字段查询条件 -->
<if test="putawayOrder != null "> and sl.putaway_order = #{putawayOrder}</if>
<if test="pickingOrder != null "> and sl.picking_order = #{pickingOrder}</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="turnoverDemand != null and turnoverDemand != ''"> and sl.turnover_demand = #{turnoverDemand}</if>
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
</select>
</mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论