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,6 +29,12 @@
></el-button>
</template>
</el-input>
<el-input v-model="form.materialId" type="hidden" />
</el-form-item>
</el-col>
</el-row>
<!-- 选择物料的弹窗 -->
<el-dialog
v-if="!isMaterialLocked"
title="选择物料"
......@@ -53,10 +59,8 @@
<el-button type="primary" @click.native="confirmMaterialSelect">确认选择</el-button>
</div>
</el-dialog>
</el-form-item>
</el-col>
</el-row>
<!-- 库存信息列表 -->
<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;"
......@@ -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);
......@@ -521,7 +525,6 @@ export default {
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);
......@@ -533,28 +536,30 @@ export default {
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.warehousesId === detail.warehousesId &&
row.locationId === detail.locationId
);
}
// 方案3:终极兜底(如果允许“无匹配则不回显”,可去掉这一步)
if (!targetRow) {
targetRow = this.inventoryList.find(row =>
row.batchId === detail.batchId &&
row.materialId === detail.materialId
);
}
if (!targetRow) {
console.warn('【匹配失败】明细无对应库存行,detail.inventoryId=', detail.inventoryId);
return; // 跳过当前明细的回显
return;
}
// 3. 给匹配到的库存行赋值回显数据
this.$set(targetRow, 'actualQuantity', detail.actualQuantity ?? null);
this.$set(targetRow, 'plannedQuantity', detail.plannedQuantity ?? null);
this.$set(targetRow, 'divisor', detail.divisor ?? null);
......@@ -563,18 +568,20 @@ export default {
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);
});
// 4. 同步明细数据(保持页面显示一致)
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) {
// 1. 检查选择器组件是否存在
if (!this.$refs.materialsSeletor) {
this.$message.error('物料选择器组件加载失败,请重试');
return;
}
// 2. 异步等待组件数据同步(避免取值过早)
this.$nextTick(() => {
// 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;
}
this.$set(this.form, 'materialId', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
this.$set(this.form, 'materialUuids', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
// 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(() => {
if (this.$refs.detailForm) {
this.$refs.detailForm.validateField('materialId');
}
this.$refs.detailForm?.validateField('materialId');
});
});
}
},
......
......@@ -21,6 +21,14 @@
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
icon="el-icon-delete"
......@@ -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;
......@@ -356,10 +403,17 @@ public class Inventory extends BaseEntity
.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())
......@@ -376,6 +430,7 @@ public class Inventory extends BaseEntity
.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,6 +126,14 @@ public class Owners extends BaseEntity
return contactPerson;
}
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;
......
......@@ -14,116 +14,118 @@ import java.util.Date;
* @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;
......@@ -139,6 +140,11 @@ public class InventoryServiceImpl implements IInventoryService
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){
......
......@@ -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,8 +26,7 @@ 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;
......@@ -33,8 +37,7 @@ public class OwnersServiceImpl implements IOwnersService
* @return 货主信息
*/
@Override
public Owners selectOwnersById(String id)
{
public Owners selectOwnersById(String id) {
return ownersMapper.selectOwnersById(id);
}
......@@ -45,8 +48,7 @@ public class OwnersServiceImpl implements IOwnersService
* @return 货主信息
*/
@Override
public List<Owners> selectOwnersList(Owners owners)
{
public List<Owners> selectOwnersList(Owners owners) {
return ownersMapper.selectOwnersList(owners);
}
......@@ -57,40 +59,36 @@ public class OwnersServiceImpl implements IOwnersService
* @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="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
......
<?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">
......@@ -19,20 +19,24 @@ 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
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>
......@@ -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>
......@@ -77,6 +83,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<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>
......@@ -92,12 +100,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</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">
update owners
<trim prefix="SET" suffixOverrides=",">
<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>
......
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论