Commit 6a8bfd30 by yubin

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	ruoyi-admin-vue/src/views/inventory/locations/index.vue
#	ruoyi-admin-vue/src/views/inventory/orders/OutboundOrderFormWithItems.vue
#	ruoyi-admin-vue/src/views/inventory/orders/index.vue
parents 1f9d9564 92616d3e
......@@ -47,10 +47,10 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="批次ID" prop="batchId">
<el-form-item label="批次" prop="batchId">
<el-input
v-model="queryParams.batchId"
placeholder="请输入批次ID"
placeholder="请输入批次"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -286,8 +286,8 @@ export default {
this.queryParams.warehouseId = warehouse.warehouseId
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
......@@ -296,8 +296,8 @@ export default {
this.queryWarehouseName = null
this.queryParams.warehouseId = null
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
......
......@@ -134,6 +134,20 @@
/>
</el-select>
</el-form-item>
<!-- ========== 新增:入库日期范围选择器 ========== -->
<el-form-item label="入库日期" prop="inboundDateRange">
<el-date-picker
v-model="inboundDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</page-wrapper-search>
<!-- 表格区域(对齐字典页面的样式) -->
......@@ -494,6 +508,8 @@ export default {
},
data() {
return {
// 日期组件返回数组
inboundDateRange: null,
// 货主选择相关(对齐退库组件)
queryOwnerName: null,
ownerSelectorVisible: false,
......@@ -548,7 +564,9 @@ export default {
ownerName: null, // 货主名称(搜索用)
ownerCode: null, // 货主编码(搜索用)
orderStatus: null,
orderType: null
orderType: null,
inboundDateStart: null,// 开始日期(搜索用)
inboundDateEnd: null // 结束日期(搜索用)
},
// 表单参数(对齐退库组件的货主字段)
form: {
......@@ -611,7 +629,6 @@ export default {
getList() {
this.loading = true
listInbound(this.queryParams).then(response => {
console.log(response.rows)
this.inboundList = response.rows
this.total = response.total
this.loading = false
......@@ -654,6 +671,14 @@ export default {
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
if (Array.isArray(this.inboundDateRange) && this.inboundDateRange.length === 2) {
this.queryParams.inboundDateStart = this.inboundDateRange[0];
this.queryParams.inboundDateEnd = this.inboundDateRange[1];
} else {
// 清空开始/结束日期(避免残留旧值)
this.queryParams.inboundDateStart = "";
this.queryParams.inboundDateEnd = "";
}
this.getList()
},
......@@ -673,8 +698,11 @@ export default {
ownerName: null,
ownerCode: null,
orderStatus: null,
orderType: null
orderType: null,
inboundDateStart: null,
inboundDateEnd: null
}
this.inboundDateRange = null;
this.$nextTick(() => {
// 重新触发查询,加载默认数据
this.handleQuery()
......
......@@ -752,7 +752,7 @@ export default {
const errors = []
this.displayData.forEach((item, index) => {
if (!item.materialId) {
errors.push(`第${index + 1}行:货物ID不能为空`)
errors.push(`第${index + 1}行:货物不能为空`)
}
if (parseFloat(item.actualQuantity) <= 0) {
errors.push(`第${index + 1}实际数量必须大于0`)
......
......@@ -56,7 +56,7 @@
<el-form-item label="物料" prop="materialId">
<el-input
v-model="queryParams.materialId"
placeholder="请输入物料ID或编码"
placeholder="请输入物料或编码"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -81,11 +81,9 @@
<el-form-item label="库位" prop="locationId">
<el-input
v-model="queryLocationName"
placeholder="请选择库位"
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!queryParams.warehouseId"
>
<template v-if="queryLocationName" #suffix>
<i
......@@ -411,23 +409,23 @@ export default {
if (!warehouse) return
this.queryParams.warehouseId = warehouse.warehouseId
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
clearQueryWarehouse() {
this.queryWarehouseName = null
this.queryParams.warehouseId = null
this.queryParams.warehousesCode = null
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
openLocationSelector() {
if (!this.queryParams.warehouseId) {
this.$message.warning("请先选择仓库")
return
}
// if (!this.queryParams.warehouseId) {
// this.$message.warning("请先选择仓库")
// return
// }
this.locationSelectorVisible = true
},
handleLocationSelected(location) {
......
......@@ -71,7 +71,6 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 注释掉仓库查询相关 -->
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="queryWarehouseName"
......@@ -222,17 +221,15 @@
</el-col>
</el-row>
<el-row :gutter="20" style="margin: 10px 0;">
<!-- 注释掉物料分类相关 -->
<!-- <el-col :span="24">
<el-col :span="24">
<div><strong>允许存放物料名称:</strong>{{ scope.row.allowedCategoryNames || '-' }}</div>
</el-col> -->
</el-col>
</el-row>
</template>
</el-table-column>
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="库位编码" align="center" prop="locationCode" width="120" fixed />
<el-table-column label="库位名称" align="center" prop="locationName" width="150" />
<!-- 注释掉仓库列 -->
<!-- <el-table-column label="仓库" align="center" prop="warehousesName" width="180">
<template slot-scope="scope">
{{ scope.row.warehousesName }}
......@@ -266,8 +263,7 @@
<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" />
<!-- 注释掉物料分类列 -->
<!-- <el-table-column label="允许存放的物料名称" align="center" prop="allowedCategoryNames" width="200">
<el-table-column label="允许存放的物料名称" align="center" prop="allowedCategoryNames" width="200">
<template slot-scope="scope">
<el-tooltip
:content="scope.row.allowedCategoryNames"
......@@ -297,7 +293,7 @@
</div>
</el-tooltip>
</template>
</el-table-column> -->
</el-table-column>
<el-table-column label="温区" align="center" prop="temperatureZone" width="100" />
<el-table-column label="应用状态" align="center" prop="isEnabled" width="100">
<template slot-scope="scope">
......@@ -361,7 +357,6 @@
</el-form-item>
</el-col>
</el-row>
<!-- 注释掉仓库选择 -->
<!-- <el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="form.warehouseName"
......@@ -515,8 +510,7 @@
<el-input v-model="form.allowedHazardLevels" placeholder="请输入允许存放的危险等级" />
</el-form-item>
</el-col>
<!-- 注释掉物料分类选择 -->
<!-- <el-col :span="12">
<el-col :span="12">
<el-form-item label="允许存放物料" prop="allowedCategoryIds">
<div style="display: flex; align-items: center; flex-direction: column; gap: 8px;">
<el-input
......@@ -528,7 +522,7 @@
/>
</div>
</el-form-item>
</el-col> -->
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
......@@ -555,8 +549,8 @@
</div>
</el-dialog>
<!-- 注释掉物料选择对话框 -->
<!-- <el-dialog
<!-- 选择允许存放的物料对话框 -->
<el-dialog
title="选择允许存放的物料"
:visible.sync="showMaterialSelect"
width="1000px"
......@@ -576,7 +570,7 @@
<el-button @click="handleMaterialSelectionCancel">取消</el-button>
<el-button type="primary" @click="confirmMaterialSelection">确认选择</el-button>
</div>
</el-dialog> -->
</el-dialog>
<!-- 导入组件 -->
<import-excel
......@@ -588,7 +582,7 @@
@success="getList"
/>
<!-- 注释掉仓库选择器组件 -->
<!-- 仓库选择器组件 -->
<!-- <WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
......@@ -598,24 +592,15 @@
<script>
import { listLocations, getLocations, delLocations, addLocations, updateLocations } from "@/api/inventory/locations"
// 注释掉仓库相关api
// import { listWarehouses } from "@/api/inventory/warehouses"
// 注释掉物料选择器组件
// import materialsSeletor from "../../../components/materialsSeletor.vue"
// 注释掉仓库选择器组件
import { listWarehouses } from "@/api/inventory/warehouses"
import materialsSeletor from "../../../components/materialsSeletor.vue"
// import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import ImportExcel from "@/components/ImportExcel/index"
// 注释掉物料相关api
// import { listMaterials } from "@/api/inventory/materials"
import { listMaterials } from "@/api/inventory/materials"
export default {
name: "Locations",
components: {
// 注释掉物料选择器和仓库选择器组件
// materialsSeletor,
// WarehouseSelector,
ImportExcel
},
components: { materialsSeletor, ImportExcel },
dicts: ['sys_normal_disable', 'location_type', 'location_usage', 'yorn','is_enabled'],
data() {
return {
......@@ -635,8 +620,7 @@ export default {
pageSize: 10,
locationCode: null,
locationName: null,
// 注释掉仓库查询参数
// warehouseId: null,
warehouseId: null,
locationType: null,
layerCode: null,
locationUsage: null,
......@@ -650,9 +634,8 @@ export default {
id: null,
locationCode: null,
locationName: null,
// 注释掉仓库相关字段
// warehouseId: null,
// warehouseName: null,
warehouseId: null,
warehouseName: null,
locationType: null,
zoneCode: null,
rowCode: null,
......@@ -661,9 +644,8 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
// 注释掉物料分类相关字段
// allowedCategoryIds: null, // 原materialCodes
// allowedCategoryNames: null, // 原materialNames
allowedCategoryIds: null, // 原materialCodes
allowedCategoryNames: null, // 原materialNames
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
......@@ -688,7 +670,6 @@ export default {
{ required: true, message: '库位名称不能为空', trigger: 'blur' },
{ min: 1, max: 100, message: '库位名称长度不能超过100个字符', trigger: 'blur' }
],
// 注释掉仓库验证规则
// warehouseId: [
// { required: true, message: '仓库不能为空', trigger: 'change' }
// ],
......@@ -707,173 +688,172 @@ export default {
isEnabled: [
{ required: true, message: '应用状态不能为空', trigger: 'change' }
]
// 注释掉物料分类验证规则
// allowedCategoryIds: [
// { required: true, message: '允许存放物料不能为空', trigger: 'change' }
// ]
},
// 注释掉仓库相关数据
// warehouseList: [],
// loadingWarehouse: false,
// queryWarehouseName: '',
// 注释掉物料选择相关数据
// showMaterialSelect: false,
// tempSelectedMaterials: {
// materialCodes: [],
// names: [],
// categoryIds: []
// },
// materialCodeToNameMap: {},
// materialMapLoaded: false,
// 注释掉仓库选择器相关数据
// warehouseSelectorVisible: false,
// warehouseSelectTarget: '',
// currentDetailItem: null
// 仓库相关
warehouseList: [],
loadingWarehouse: false,
queryWarehouseName: '',
// 物料选择相关
showMaterialSelect: false,
tempSelectedMaterials: {
materialCodes: [],
names: [],
categoryIds: []
},
materialCodeToNameMap: {},
materialMapLoaded: false,
// 仓库选择器相关
warehouseSelectorVisible: false,
warehouseSelectTarget: '',
currentDetailItem: null
}
},
created() {
console.log('【Locations组件】开始初始化')
this.getList()
// 注释掉仓库列表和物料映射表初始化
// this.getWarehouseList()
// this.initMaterialCodeToNameMap()
this.getWarehouseList()
this.initMaterialCodeToNameMap()
},
methods: {
// 注释掉物料选择器初始化方法
// initMaterialSelector() {
// console.log('【初始化物料选择器】清空残留数据')
// this.tempSelectedMaterials = {
// materialCodes: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : []) : [],
// names: this.form.id ? (this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : []) : [],
// categoryIds: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []) : []
// }
// this.$nextTick(() => {
// this.showMaterialSelect = true
// if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
// this.$refs.materialsSeletor.clearSelection()
// if (this.form.id) {
// this.$refs.materialsSeletor.setSelection(this.tempSelectedMaterials.materialCodes)
// }
// }
// })
// },
// 注释掉清空查询仓库方法
// clearQueryWarehouse() {
// console.log('【清空查询仓库】执行清空操作')
// this.queryWarehouseName = ''
// this.queryParams.warehouseId = null
// this.handleQuery()
// },
// 注释掉清空表单仓库方法
// clearFormWarehouse() {
// console.log('【清空表单仓库】执行清空操作')
// this.form.warehouseName = ''
// this.form.warehouseId = null
// },
// 注释掉仓库选择回调方法
// handleWarehouseSelected(warehouse) {
// console.log('【仓库选择回调】选中的仓库数据:', warehouse)
// if (!warehouse) return
// const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id
// const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName
// if (this.warehouseSelectTarget === 'query') {
// this.queryParams.warehouseId = warehouseId
// this.queryWarehouseName = warehouseName
// this.handleQuery()
// } else {
// this.form.warehouseId = warehouseId
// this.form.warehouseName = warehouseName
// if (this.currentDetailItem) {
// this.currentDetailItem.warehouseId = warehouseId
// this.currentDetailItem.warehouseName = warehouseName
// }
// }
// this.warehouseSelectorVisible = false
// },
// 注释掉打开仓库选择器方法
// openWarehouseSelector(target = 'form') {
// console.log('【打开仓库选择器】目标:', target)
// this.warehouseSelectTarget = target
// this.warehouseSelectorVisible = true
// },
// 注释掉获取仓库列表方法
// getWarehouseList() {
// console.log('【获取仓库列表】开始请求仓库数据')
// this.loadingWarehouse = true
// listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => {
// console.log('【获取仓库列表】请求成功,返回数据:', response)
// this.warehouseList = response.rows || []
// this.loadingWarehouse = false
// }).catch(error => {
// console.error('【获取仓库列表】请求失败:', error)
// this.warehouseList = []
// this.loadingWarehouse = false
// })
// },
// 注释掉根据仓库ID获取名称方法
// getWarehouseNameById(warehouseId) {
// console.log('【根据仓库ID获取名称】仓库ID:', warehouseId)
// if (!warehouseId) return '-'
// const warehouse = this.warehouseList.find(item =>
// item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId
// )
// const warehouseName = warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-'
// console.log('【根据仓库ID获取名称】匹配到的仓库名称:', warehouseName)
// return warehouseName
// },
// 注释掉初始化物料编码-名称映射表方法
// async initMaterialCodeToNameMap() {
// console.log('【初始化物料映射表】开始加载物料数据')
// try {
// this.materialMapLoaded = true
// let pageNum = 1
// const pageSize = 1000
// let hasMore = true
// this.materialCodeToNameMap = {}
// while (hasMore) {
// console.log(`【初始化物料映射表】请求第${pageNum}页物料数据,每页${pageSize}条`)
// const response = await listMaterials({
// pageNum,
// pageSize,
// isUsed: 1,
// materialCode: null,
// materialName: null
// })
// if (response.rows && response.rows.length) {
// console.log(`【初始化物料映射表】第${pageNum}页返回${response.rows.length}条物料数据`)
// response.rows.forEach(item => {
// if (item.materialCode && item.materialName) {
// const code = item.materialCode.trim().toUpperCase()
// this.materialCodeToNameMap[code] = item.materialName
// }
// })
// hasMore = pageNum * pageSize < response.total
// pageNum++
// } else {
// hasMore = false
// }
// }
// console.log('【初始化物料映射表】完成,映射表长度:', Object.keys(this.materialCodeToNameMap).length)
// } catch (error) {
// console.error('【初始化物料映射表】失败:', error)
// this.materialMapLoaded = false
// this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
// }
// },
// ========== 新增:初始化物料选择器(核心修复数据残留) ==========
initMaterialSelector() {
console.log('【初始化物料选择器】清空残留数据')
// 1. 清空临时选择数据(区分新增/修改)
this.tempSelectedMaterials = {
materialCodes: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : []) : [],
names: this.form.id ? (this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : []) : [],
categoryIds: this.form.id ? (this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []) : []
}
// 2. 延迟打开弹窗,确保数据先清空
this.$nextTick(() => {
this.showMaterialSelect = true
// 3. 兼容子组件清空选中状态(如果有该方法)
if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
this.$refs.materialsSeletor.clearSelection()
// 修改模式下重新设置选中值
if (this.form.id) {
this.$refs.materialsSeletor.setSelection(this.tempSelectedMaterials.materialCodes)
}
}
})
},
// 清空查询仓库
clearQueryWarehouse() {
console.log('【清空查询仓库】执行清空操作')
this.queryWarehouseName = ''
this.queryParams.warehouseId = null
this.handleQuery()
},
// 清空表单仓库
clearFormWarehouse() {
console.log('【清空表单仓库】执行清空操作')
this.form.warehouseName = ''
this.form.warehouseId = null
},
// 仓库选择回调
handleWarehouseSelected(warehouse) {
console.log('【仓库选择回调】选中的仓库数据:', warehouse)
if (!warehouse) return
const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id
const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName
if (this.warehouseSelectTarget === 'query') {
this.queryParams.warehouseId = warehouseId
this.queryWarehouseName = warehouseName
this.handleQuery()
} else {
this.form.warehouseId = warehouseId
this.form.warehouseName = warehouseName
if (this.currentDetailItem) {
this.currentDetailItem.warehouseId = warehouseId
this.currentDetailItem.warehouseName = warehouseName
}
}
this.warehouseSelectorVisible = false
},
// 打开仓库选择器
openWarehouseSelector(target = 'form') {
console.log('【打开仓库选择器】目标:', target)
this.warehouseSelectTarget = target
this.warehouseSelectorVisible = true
},
// 获取仓库列表
getWarehouseList() {
console.log('【获取仓库列表】开始请求仓库数据')
this.loadingWarehouse = true
listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => {
console.log('【获取仓库列表】请求成功,返回数据:', response)
this.warehouseList = response.rows || []
this.loadingWarehouse = false
}).catch(error => {
console.error('【获取仓库列表】请求失败:', error)
this.warehouseList = []
this.loadingWarehouse = false
})
},
// 根据仓库ID获取仓库名称
getWarehouseNameById(warehouseId) {
console.log('【根据仓库ID获取名称】仓库ID:', warehouseId)
if (!warehouseId) return '-'
const warehouse = this.warehouseList.find(item =>
item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId
)
const warehouseName = warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-'
console.log('【根据仓库ID获取名称】匹配到的仓库名称:', warehouseName)
return warehouseName
},
// 初始化物料编码-名称映射表
async initMaterialCodeToNameMap() {
console.log('【初始化物料映射表】开始加载物料数据')
try {
this.materialMapLoaded = true
let pageNum = 1
const pageSize = 1000
let hasMore = true
this.materialCodeToNameMap = {}
while (hasMore) {
console.log(`【初始化物料映射表】请求第${pageNum}页物料数据,每页${pageSize}条`)
const response = await listMaterials({
pageNum,
pageSize,
isUsed: 1,
materialCode: null,
materialName: null
})
if (response.rows && response.rows.length) {
console.log(`【初始化物料映射表】第${pageNum}页返回${response.rows.length}条物料数据`)
response.rows.forEach(item => {
if (item.materialCode && item.materialName) {
const code = item.materialCode.trim().toUpperCase()
this.materialCodeToNameMap[code] = item.materialName
}
})
hasMore = pageNum * pageSize < response.total
pageNum++
} else {
hasMore = false
}
}
console.log('【初始化物料映射表】完成,映射表长度:', Object.keys(this.materialCodeToNameMap).length)
} catch (error) {
console.error('【初始化物料映射表】失败:', error)
this.materialMapLoaded = false
this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
}
},
// 行点击事件
handleRowClick(row, event, column) {
......@@ -890,9 +870,8 @@ export default {
const params = {
...this.queryParams,
isUsed: 1,
// 注释掉仓库ID参数
// warehousesId: this.queryParams.warehouseId,
// warehouseId: undefined
warehousesId: this.queryParams.warehouseId,
warehouseId: undefined
}
console.log('【获取库位列表】最终请求参数:', params)
listLocations(params).then(response => {
......@@ -923,8 +902,7 @@ export default {
pageSize: 10,
locationCode: null,
locationName: null,
// 注释掉仓库查询参数
// warehouseId: null,
warehouseId: null,
locationType: null,
layerCode: null,
locationUsage: null,
......@@ -932,8 +910,7 @@ export default {
zoneCode: null,
pickingArea: null
}
// 注释掉查询仓库名称重置
// this.queryWarehouseName = ''
this.queryWarehouseName = ''
this.getList()
},
......@@ -973,68 +950,73 @@ export default {
// 映射后端字段到前端
const formData = {
...rowData,
// 注释掉仓库相关字段映射
// warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id,
// warehousesId: undefined
warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id,
warehousesId: undefined
}
this.form = JSON.parse(JSON.stringify(formData))
// 注释掉仓库名称设置
// if (this.form.warehouseId) {
// this.form.warehouseName = this.getWarehouseNameById(this.form.warehouseId)
// }
// 注释掉物料映射表初始化
// await this.initMaterialCodeToNameMap()
// 注释掉物料编码和名称处理
// let materialCodes = []
// let materialNames = []
// if (Array.isArray(rowData.allowedCategoryIds) && rowData.allowedCategoryIds.length) {
// materialCodes = rowData.allowedCategoryIds
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// }
// else if (rowData.allowedCategoryIds) {
// materialCodes = rowData.allowedCategoryIds.split(',')
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// }
// if (Array.isArray(rowData.allowedCategoryNames) && rowData.allowedCategoryNames.length) {
// materialNames = rowData.allowedCategoryNames
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// }
// else if (rowData.allowedCategoryNames) {
// materialNames = rowData.allowedCategoryNames.split(',')
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// }
// else if (materialCodes.length) {
// materialNames = materialCodes.map(code => {
// return this.materialCodeToNameMap[code] || `【未匹配】${code}`
// })
// }
// let categoryIds = materialCodes
// this.form.allowedCategoryIds = materialCodes.join(',')
// this.form.allowedCategoryNames = materialNames.join(',')
// this.tempSelectedMaterials = {
// materialCodes: materialCodes,
// names: materialNames,
// categoryIds: categoryIds
// }
// console.log('【修改库位】处理后的物料数据:', {
// allowedCategoryIds: this.form.allowedCategoryIds,
// allowedCategoryNames: this.form.allowedCategoryNames
// })
// 设置仓库名称
if (this.form.warehouseId) {
this.form.warehouseName = this.getWarehouseNameById(this.form.warehouseId)
}
await this.initMaterialCodeToNameMap()
// 处理物料编码和名称(支持数组或字符串格式)
let materialCodes = []
let materialNames = []
// 优先从allowedCategoryIds数组读取(原materialIds)
if (Array.isArray(rowData.allowedCategoryIds) && rowData.allowedCategoryIds.length) {
materialCodes = rowData.allowedCategoryIds
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
}
// 兼容字符串格式
else if (rowData.allowedCategoryIds) {
materialCodes = rowData.allowedCategoryIds.split(',')
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
}
// 处理物料名称
if (Array.isArray(rowData.allowedCategoryNames) && rowData.allowedCategoryNames.length) {
materialNames = rowData.allowedCategoryNames
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
}
else if (rowData.allowedCategoryNames) {
materialNames = rowData.allowedCategoryNames.split(',')
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
}
// 兜底:通过物料编码映射名称
else if (materialCodes.length) {
materialNames = materialCodes.map(code => {
return this.materialCodeToNameMap[code] || `【未匹配】${code}`
})
}
// 处理分类ID(现在存储的是物料编码)
let categoryIds = materialCodes
// 更新表单数据
this.form.allowedCategoryIds = materialCodes.join(',')
this.form.allowedCategoryNames = materialNames.join(',')
// 更新临时选择数据
this.tempSelectedMaterials = {
materialCodes: materialCodes,
names: materialNames,
categoryIds: categoryIds
}
console.log('【修改库位】处理后的物料数据:', {
allowedCategoryIds: this.form.allowedCategoryIds,
allowedCategoryNames: this.form.allowedCategoryNames
})
this.open = true
this.title = "修改库位"
......@@ -1050,27 +1032,26 @@ export default {
this.$refs["form"].validate(valid => {
if (valid) {
console.log('【提交表单】表单验证通过,开始格式化数据')
// 注释掉物料字段格式化
// const formatField = (value) => {
// if (!value) return ''
// const result = value.split(',')
// .filter(item => item && item.trim())
// .filter((item, index, self) => self.indexOf(item) === index)
// .join(',')
// console.log(`【提交表单】格式化字段值 "${value}" 结果: "${result}"`)
// return result
// }
// this.form.allowedCategoryIds = formatField(this.form.allowedCategoryIds)
// this.form.allowedCategoryNames = formatField(this.form.allowedCategoryNames)
// 格式化物料相关字段(去重、过滤空值)
const formatField = (value) => {
if (!value) return ''
const result = value.split(',')
.filter(item => item && item.trim())
.filter((item, index, self) => self.indexOf(item) === index)
.join(',')
console.log(`【提交表单】格式化字段值 "${value}" 结果: "${result}"`)
return result
}
this.form.allowedCategoryIds = formatField(this.form.allowedCategoryIds)
this.form.allowedCategoryNames = formatField(this.form.allowedCategoryNames)
// 转换表单数据
const submitData = {
...this.form,
// 注释掉仓库相关字段转换
// warehousesId: this.form.warehouseId,
// warehouseId: undefined,
// warehouseName: undefined
warehousesId: this.form.warehouseId,
warehouseId: undefined,
warehouseName: undefined
}
console.log('【提交表单】最终提交数据:', submitData)
......@@ -1119,71 +1100,76 @@ export default {
console.log('【导出库位】执行导出操作,查询参数:', this.queryParams)
const exportParams = {
...this.queryParams,
// 注释掉仓库导出参数
// warehousesId: this.queryParams.warehouseId,
// warehouseId: undefined
warehousesId: this.queryParams.warehouseId,
warehouseId: undefined
}
console.log('【导出库位】最终导出参数:', exportParams)
this.download('inventory/locations/export', exportParams, `locations_${new Date().getTime()}.xlsx`)
},
// 注释掉物料选择变化方法
// handleMaterialSelectionChange(selectedData) {
// console.log('【物料选择变化】接收到的选择数据:', selectedData)
// const materialCodes = (selectedData.materialIds || [])
// .filter(code => code && code.trim())
// .map(code => code.trim().toUpperCase())
// .filter((code, index, self) => self.indexOf(code) === index)
// const names = (selectedData.names || [])
// .filter(name => name && name.trim())
// .filter((name, index, self) => self.indexOf(name) === index)
// const categoryIds = materialCodes
// this.tempSelectedMaterials = {
// materialCodes,
// names,
// categoryIds
// }
// console.log('【物料选择变化】处理后的临时选择数据:', this.tempSelectedMaterials)
// },
// 注释掉取消物料选择方法
// handleMaterialSelectionCancel() {
// console.log('【取消物料选择】执行取消操作,恢复原有选择状态')
// this.showMaterialSelect = false
// this.tempSelectedMaterials = {
// materialCodes: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : [],
// names: this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : [],
// categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
// }
// console.log('【取消物料选择】恢复后的临时选择数据:', this.tempSelectedMaterials)
// },
// 注释掉确认物料选择方法
// confirmMaterialSelection() {
// console.log('【确认物料选择】当前临时选择数据:', this.tempSelectedMaterials)
// if (!this.tempSelectedMaterials.materialCodes.length) {
// console.warn('【确认物料选择】未选择任何物料,提示用户')
// this.$modal.msgWarning('请至少选择一个物料!')
// return
// }
// this.form.allowedCategoryIds = this.tempSelectedMaterials.materialCodes.join(',')
// this.form.allowedCategoryNames = this.tempSelectedMaterials.names.join(',')
// console.log('【确认物料选择】更新后的表单物料数据:', {
// allowedCategoryIds: this.form.allowedCategoryIds,
// allowedCategoryNames: this.form.allowedCategoryNames
// })
// this.showMaterialSelect = false
// this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
// },
// 物料选择变化
handleMaterialSelectionChange(selectedData) {
console.log('【物料选择变化】接收到的选择数据:', selectedData)
// 修复:从selectedData中取materialIds(而非materialCodes)
const materialCodes = (selectedData.materialIds || [])
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
// 物料名称取selectedData.names
const names = (selectedData.names || [])
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
// 分类ID取selectedData.categoryIds(现在存储的是物料编码)
const categoryIds = materialCodes
this.tempSelectedMaterials = {
materialCodes,
names,
categoryIds
}
console.log('【物料选择变化】处理后的临时选择数据:', this.tempSelectedMaterials)
},
// 取消物料选择
handleMaterialSelectionCancel() {
console.log('【取消物料选择】执行取消操作,恢复原有选择状态')
this.showMaterialSelect = false
// 恢复原有选择状态
this.tempSelectedMaterials = {
materialCodes: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(u => u.trim()) : [],
names: this.form.allowedCategoryNames ? this.form.allowedCategoryNames.split(',').filter(n => n.trim()) : [],
categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
}
console.log('【取消物料选择】恢复后的临时选择数据:', this.tempSelectedMaterials)
},
// 确认物料选择
confirmMaterialSelection() {
console.log('【确认物料选择】当前临时选择数据:', this.tempSelectedMaterials)
// 修复:判断tempSelectedMaterials.materialCodes是否有值
if (!this.tempSelectedMaterials.materialCodes.length) {
console.warn('【确认物料选择】未选择任何物料,提示用户')
this.$modal.msgWarning('请至少选择一个物料!')
return
}
// 更新表单数据(确保去重和过滤)
this.form.allowedCategoryIds = this.tempSelectedMaterials.materialCodes.join(',')
this.form.allowedCategoryNames = this.tempSelectedMaterials.names.join(',')
console.log('【确认物料选择】更新后的表单物料数据:', {
allowedCategoryIds: this.form.allowedCategoryIds,
allowedCategoryNames: this.form.allowedCategoryNames
})
this.showMaterialSelect = false
this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
},
// 导入库位
handleImport() {
......@@ -1198,9 +1184,8 @@ export default {
id: null,
locationCode: null,
locationName: null,
// 注释掉仓库相关字段重置
// warehouseId: null,
// warehouseName: null,
warehouseId: null,
warehouseName: null,
locationType: null,
zoneCode: null,
rowCode: null,
......@@ -1209,9 +1194,8 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
// 注释掉物料分类相关字段重置
// allowedCategoryIds: null,
// allowedCategoryNames: null,
allowedCategoryIds: null, // 原materialCodes
allowedCategoryNames: null, // 原materialNames
temperatureZone: null,
isEnabled: 1,
isUsed: 1,
......@@ -1225,16 +1209,15 @@ export default {
allowMixedProducts: null,
allowMixedBatches: null
}
// 注释掉物料选择临时数据重置
// this.tempSelectedMaterials = {
// materialCodes: [],
// names: [],
// categoryIds: []
// }
// 注释掉物料选择器清空
// if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
// this.$refs.materialsSeletor.clearSelection()
// }
this.tempSelectedMaterials = {
materialCodes: [],
names: [],
categoryIds: []
}
// 修复:清空物料选择器残留
if (this.$refs.materialsSeletor && this.$refs.materialsSeletor.clearSelection) {
this.$refs.materialsSeletor.clearSelection()
}
if (this.$refs.form) {
this.$refs.form.resetFields()
}
......
......@@ -11,7 +11,7 @@
<el-form ref="detailForm" :model="form" label-width="100px" :rules="rules">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="货物ID" prop="materialId">
<el-form-item label="货物" prop="materialId">
<el-input
v-model="form.materialName"
placeholder="请选择物料"
......@@ -49,13 +49,12 @@
<div style="height: 70vh; overflow: auto; padding: 0 10px;">
<MaterialSelector
ref="materialsSeletor"
@selection-change="handleMaterialSelectionChange"
:selected-material-ids="form.materialId ? [form.materialId] : []"
:orders-id="ordersId || outboundOrderId"
@selection-change="confirmMaterialSelect"
:selected-material-codes="form.materialUuids ? [form.materialUuids] : []"
:multiple="false"
:detail-list="details"
/>
</div>
</el-dialog>
<!-- 库存信息列表 -->
......@@ -77,7 +76,7 @@
:row-key="item => item.inventoryId"
>
<el-table-column prop="materialName" label="物料名称" width="180" />
<el-table-column prop="batchId" label="批次" width="150" />
<el-table-column prop="batchId" label="批次" width="150" />
<el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column
......@@ -222,9 +221,10 @@
:row-key="item => item.inventoryId"
>
<el-table-column prop="materialName" label="物料名称" width="180" />
<el-table-column prop="batchId" label="批次ID" width="150" />
<el-table-column prop="batchId" label="批次" width="150" />
<el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column prop="plannedQuantity" label="计划数量" width="100" />
<el-table-column prop="actualQuantity" label="实际数量" width="100" fixed="right"/>
<el-table-column prop="unitPrice" label="单价" width="100" />
......@@ -345,10 +345,6 @@ export default {
return this.initDetails.length > 0 || !!this.initForm.materialId;
}
},
created() {
console.log('子组件接收的 ordersId:', this.ordersId);
console.log('子组件接收的 initDetails:', this.initDetails);
},
watch: {
open: {
handler(newVal) {
......@@ -363,10 +359,7 @@ export default {
this.selectedMaterialId = this.form.materialId || '';
this.selectedMaterialInfo = null;
this.currentSelectedRowId = null;
// 初始化 details:使用传入的 initDetails
this.details = this.initDetails.length > 0
? JSON.parse(JSON.stringify(this.initDetails))
: [];
this.details = this.initDetails.length > 0 ? JSON.parse(JSON.stringify(this.initDetails)) : [];
this.$nextTick(async () => {
if (this.form.materialId && this.form.materialId.trim()) {
await this.handleMaterialIdChange();
......@@ -521,8 +514,6 @@ export default {
} finally {
this.$nextTick(() => {
this.closeLoading();
// 主动触发明细同步,确保 details 有初始值
this.syncDetails(false);
});
}
},
......@@ -613,46 +604,25 @@ export default {
this.$set(row, 'plannedQuantity', 1);
}
},
syncDetails(strict = true) {
// 改造后的 syncDetails:仅校验有实际数量的行,且有值才校验
syncDetails(strict = true) {
this.details = [];
const errorMessages = [];
const errorMessages = []; // 收集有值但不合规的字段提示
let validRows = [];
if (!strict) {
validRows = this.inventoryList.filter(row => {
return row.actualQuantity !== null ||
row.plannedQuantity !== null ||
row.unitPrice !== null ||
row.labelColor !== '' ||
row.voucherNumber !== '' ||
row.shippedBy !== '';
});
validRows.forEach((row, index) => {
const availableQty = (row.quantity || 0) - (row.lockedQuantity || 0);
if (row.actualQuantity !== null && row.actualQuantity < 1) {
this.$set(row, 'actualQuantity', 1);
}
if (row.actualQuantity !== null && row.actualQuantity > availableQty) {
this.$set(row, 'actualQuantity', availableQty);
}
if (row.plannedQuantity !== null && row.plannedQuantity < 1) {
this.$set(row, 'plannedQuantity', 1);
}
if (row.plannedQuantity !== null && row.plannedQuantity > availableQty) {
this.$set(row, 'plannedQuantity', availableQty);
}
});
} else {
// 第一步:先过滤出「实际数量有值」的行(核心:无实际数量的行直接排除)
const rowsWithActualQty = this.inventoryList.filter(row => {
return row.actualQuantity !== null && row.actualQuantity !== undefined;
});
if (strict && rowsWithActualQty.length > 0) {
// 严格模式:仅校验有实际数量的行,且「有值才校验」
validRows = rowsWithActualQty.filter((row, index) => {
const rowErrors = [];
const rowName = `第${index + 1}行【${row.materialName || '未知物料'}】`;
const availableQty = (row.quantity || 0) - (row.lockedQuantity || 0);
// 1. 实际数量(必校验,因为能走到这步说明有值)
if (row.actualQuantity < 1) {
rowErrors.push('实际数量不能小于1');
}
......@@ -660,6 +630,7 @@ export default {
rowErrors.push(`实际数量不能超过可用库存(${availableQty})`);
}
// 2. 计划数量(有值才校验)
if (row.plannedQuantity !== null && row.plannedQuantity !== undefined) {
if (row.plannedQuantity < 1) {
rowErrors.push('计划数量不能小于1');
......@@ -667,14 +638,19 @@ export default {
if (row.plannedQuantity > availableQty) {
rowErrors.push(`计划数量不能超过可用库存(${availableQty})`);
}
} else {
}else{
rowErrors.push(`请填写计划数量`);
}
if (row.unitPrice === null || row.unitPrice === undefined || row.unitPrice <= 0) {
rowErrors.push('请填写有效的单价(大于0)');
}
// 3. 除数(有值才校验,无值不提示)
if (row.unitPrice !== null && row.unitPrice !== undefined) {
// 若有值但为0/负数,可补充校验(按需)
if (row.unitPrice <= 0) {
rowErrors.push('请填写单价');
}
}
// 收集当前行的错误(仅有值但不合规的字段)
if (rowErrors.length > 0) {
errorMessages.push(`${rowName}${rowErrors.join('、')}`);
return false;
......@@ -683,6 +659,7 @@ export default {
});
}
// 格式化通过校验的行并同步到details
validRows.forEach(row => {
const newDetail = {
inventoryId: row.inventoryId,
......@@ -707,15 +684,19 @@ export default {
this.details.push(newDetail);
});
console.log('syncDetails 执行结果:', this.details);
// 返回错误信息,供提交方法使用
return errorMessages;
},
handleSubmit() {
},
// 提交方法:集成精准提示
handleSubmit() {
// 1. 校验物料ID
if (!this.form.materialId?.trim()) {
this.$message.error('请先选择物料ID');
return;
}
// 2. 校验表单基础项
this.$refs.detailForm.validate(async (valid) => {
if (!valid) {
this.$message.error('表单校验失败,请检查必填项');
......@@ -723,9 +704,11 @@ export default {
}
console.log("syncDetails前", this.details);
// 执行明细校验,接收错误信息
const detailErrors = this.syncDetails(true);
console.log("syncDetails后", this.details);
// 3. 提示有值但不合规的字段
if (detailErrors.length > 0) {
this.$message.error({
title: '明细数据校验失败',
......@@ -737,11 +720,13 @@ export default {
return;
}
// 4. 兜底:有实际数量的行都校验通过,但无有效行(比如实际数量都<1
if (this.details.length === 0) {
this.$message.error('无有效明细数据,请检查实际数量及相关字段');
return;
}
// 5. 组装提交数据
const submitDetails = this.details.map(detail => ({
...detail,
materialName: this.form.materialName || detail.materialName,
......@@ -754,7 +739,7 @@ export default {
this.$emit('submit', submitDetails);
this.$emit('update:open', false);
});
},
},
removeDetail(row) {
this.details = this.details.filter(d => d.inventoryId !== row.inventoryId);
const inventoryRow = this.inventoryList.find(item => item.inventoryId === row.inventoryId);
......@@ -773,6 +758,7 @@ export default {
}
this.syncDetails(this.initDetails.length === 0);
},
handleClose() {
this.closeLoading();
this.$nextTick(() => {
......@@ -790,43 +776,71 @@ export default {
});
this.$emit('update:open', false);
},
handleMaterialSelectionChange(selectionData) {
console.log('传给子组件的detailList:', this.details);
// 修复:接收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', '');
if (!selectionData || !selectionData.materials) {
console.log("【物料选择清空】无有效选中数据");
return;
}
const materials = Array.isArray(selectionData.materials) ? selectionData.materials : [];
if (materials.length === 0) {
console.log("【物料选择清空】选中列表为空");
return;
console.log("【物料选择清空】");
}
},
// 修复:增强校验逻辑,增加组件存在性检查和异步同步
confirmMaterialSelect() {
// 标记为“用户主动操作”
this.isUserInitiatedSelect = true;
const firstItem = materials[0];
if (!firstItem) {
console.log("【物料选择清空】第一个选中项为空");
// 1. 检查选择器组件是否存在
if (!this.$refs.materialsSeletor) {
this.$message.error('物料选择器组件加载失败,请重试');
return;
}
this.selectedMaterialInfo = firstItem;
this.selectedMaterialId = firstItem.id || firstItem.materialId || firstItem.uuid || '';
this.$set(this.form, 'materialName', firstItem.materialName || firstItem.name || '');
this.$set(this.form, 'materialId', this.selectedMaterialId);
this.$set(this.form, 'materialUuids', this.selectedMaterialId);
// 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);
// 5. 容错处理:确保物料ID有效
const materialId = this.selectedMaterialInfo.id || this.selectedMaterialInfo.materialId || this.selectedMaterialInfo.uuid || '';
// 6. 赋值并关闭弹窗
this.$set(this.form, 'materialId', materialId);
this.$set(this.form, 'materialUuids', materialId);
this.openMaterialSelector = false;
console.log("【物料选择成功】ID:", this.selectedMaterialId, "名称:", this.form.materialName);
this.$nextTick(async () => {
await this.handleMaterialIdChange();
// 7. 查询库存并校验字段
this.handleMaterialIdChange();
this.$nextTick(() => {
this.$refs.detailForm?.validateField('materialId');
});
// 重置标记
this.isUserInitiatedSelect = false;
});
}
},
beforeDestroy() {
......
......@@ -3,16 +3,14 @@
<!-- 页面标题和操作按钮 -->
<PageTitle>
<template #buttons>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="medium"
@click="handleAdd"
v-hasPermi="['inventory:inbound:add']"
v-hasPermi="['inventory:orders:add']"
>新增</el-button>
<el-button
type="success"
plain
......@@ -20,9 +18,16 @@
size="medium"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['inventory:inbound:edit']"
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
......@@ -30,25 +35,15 @@
size="medium"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['inventory:inbound:remove']"
v-hasPermi="['inventory:orders:remove']"
>删除</el-button>
<el-button
type="warning"
plain
icon="el-icon-upload"
size="medium"
@click="handleImport"
v-hasPermi="['inventory:inbound:import']"
>导入</el-button>
<el-button
type="warning"
plain
icon="el-icon-download"
size="medium"
@click="handleExport"
v-hasPermi="['inventory:inbound:export']"
v-hasPermi="['inventory:orders:export']"
>导出</el-button>
</template>
</PageTitle>
......@@ -103,10 +98,10 @@
/>
</el-select>
</el-form-item>
<el-form-item label="批次" prop="batchCode">
<el-form-item label="批次" prop="batchCode">
<el-input
v-model="queryParams.batchCode"
placeholder="请输入批次"
placeholder="请输入批次"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -210,7 +205,7 @@
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="批次" align="center" prop="batchCode" width="120" />
<el-table-column label="批次" align="center" prop="batchCode" width="120" />
<el-table-column label="仓库" align="center" prop="warehouseName" width="120">
<template slot-scope="scope">
{{ scope.row.warehouseName || '-' }}
......@@ -341,8 +336,8 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="批次" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次" :disabled="isViewDetail || formDisabled.batchCode" />
<el-form-item label="批次" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次" :disabled="isViewDetail || formDisabled.batchCode" />
</el-form-item>
</el-col>
<el-col :span="12">
......@@ -425,10 +420,13 @@
</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;">
<!-- 【修改2】展示物料名称(优先取分组的materialName,无则用getMaterialName方法) -->
<span style="font-weight: 600; margin-right: 16px;">物料:{{ group.materialName }}</span>
<span style="color: #666;">明细数量:{{ group.items.length }} </span>
<!-- 仅编辑模式显示分组操作按钮 -->
<el-button
type="text"
size="mini"
......
......@@ -53,7 +53,6 @@
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!queryParams.warehouseId"
>
<template v-if="queryLocationName" #suffix>
<i
......@@ -67,7 +66,7 @@
<el-form-item label="物料" prop="materialId">
<el-input
v-model="queryParams.materialId"
placeholder="请输入物料ID或编码"
placeholder="请输入物料或编码"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -234,9 +233,9 @@ export default {
this.queryParams.warehouseId = warehouse.warehouseId || warehouse.id
this.queryParams.warehousesCode = warehouse.warehousesCode
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.queryParams.locationId = null
// // 仓库选择后,清空库位信息
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
/** 清空仓库选择 */
......@@ -245,16 +244,16 @@ export default {
this.queryParams.warehouseId = null
this.queryParams.warehousesCode = null
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
if (!this.queryParams.warehouseId) {
this.$message.warning("请先选择仓库")
return
}
// if (!this.queryParams.warehouseId) {
// this.$message.warning("请先选择仓库")
// return
// }
this.locationSelectorVisible = true
},
/** 库位选择回调 */
......
......@@ -50,7 +50,6 @@
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!queryParams.warehouseId"
>
<template v-if="queryLocationName" #suffix>
<i
......@@ -419,16 +418,16 @@ export default {
this.queryParams.warehousesCode = warehouse.warehousesCode
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
if (!this.queryParams.warehouseId) {
this.$message.warning("请先选择仓库")
return
}
// if (!this.queryParams.warehouseId) {
// this.$message.warning("请先选择仓库")
// return
// }
this.locationSelectorVisible = true
},
/** 库位选择回调 */
......@@ -444,8 +443,8 @@ export default {
this.queryParams.warehouseId = null
this.queryParams.warehousesCode = null
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
/** 清空库位选择 */
......@@ -512,12 +511,12 @@ export default {
// 根据当前行的物料ID、仓库、库位、货主等信息查询明细
const params = {
materialId: row.materialId,
warehousesId: row.warehousesId,
locationId: row.locationId,
ownerId: row.ownerId,
batchId: row.batchId,
inventoryType: row.inventoryType,
inventoryStatus: row.inventoryStatus,
warehousesId: this.queryParams.warehousesId,
locationId: this.queryParams.locationId,
ownerId: this.queryParams.ownerId,
batchId: this.queryParams.batchId,
inventoryType: this.queryParams.inventoryType,
inventoryStatus: this.queryParams.inventoryStatus,
pageNum: 1,
pageSize: 10000 // 设置一个很大的值,不分页
}
......
......@@ -57,7 +57,7 @@
<el-form-item label="物料" prop="materialId">
<el-input
v-model="queryParams.materialId"
placeholder="请输入物料ID或编码"
placeholder="请输入物料或编码"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -118,7 +118,7 @@
<div class="table-container">
<el-table v-loading="loading" :data="returnOrderItemList" border height="100%" style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" fixed="left" />
<!-- <el-table-column label="物料ID" align="center" prop="materialId" width="150" /> -->
<!-- <el-table-column label="物料" align="center" prop="materialId" width="150" /> -->
<el-table-column label="物料名称" align="center" prop="materialName" min-width="150" show-overflow-tooltip />
<el-table-column label="SAP物料号" align="center" prop="sapNo" width="120" />
<el-table-column label="TS Code" align="center" prop="tsCode" width="120" />
......
......@@ -9,34 +9,34 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="货物ID 字典,检索条件" prop="materialId">
<el-form-item label="货物 字典,检索条件" prop="materialId">
<el-input
v-model="queryParams.materialId"
placeholder="请输入货物ID 字典,检索条件"
placeholder="请输入货物 字典,检索条件"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="批次ID 检索条件" prop="batchCode">
<el-form-item label="批次 检索条件" prop="batchCode">
<el-input
v-model="queryParams.batchCode"
placeholder="请输入批次ID 检索条件"
placeholder="请输入批次 检索条件"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库ID 检索条件" prop="warehouseId">
<el-form-item label="仓库 检索条件" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库ID 检索条件"
placeholder="请输入仓库 检索条件"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="库位ID 检索条件" prop="locationId">
<el-form-item label="库位 检索条件" prop="locationId">
<el-input
v-model="queryParams.locationId"
placeholder="请输入库位ID 检索条件"
placeholder="请输入库位 检索条件"
clearable
@keyup.enter.native="handleQuery"
/>
......@@ -299,17 +299,17 @@
<el-form-item label="盘点单号 检索条件" prop="stocktakeId">
<el-input v-model="form.stocktakeId" placeholder="请输入盘点单号 检索条件" />
</el-form-item>
<el-form-item label="货物ID 字典,检索条件" prop="materialId">
<el-input v-model="form.materialId" placeholder="请输入货物ID 字典,检索条件" />
<el-form-item label="货物 字典,检索条件" prop="materialId">
<el-input v-model="form.materialId" placeholder="请输入货物 字典,检索条件" />
</el-form-item>
<el-form-item label="批次ID 检索条件" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次ID 检索条件" />
<el-form-item label="批次 检索条件" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次 检索条件" />
</el-form-item>
<el-form-item label="仓库ID 检索条件" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID 检索条件" />
<el-form-item label="仓库 检索条件" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库 检索条件" />
</el-form-item>
<el-form-item label="库位ID 检索条件" prop="locationId">
<el-input v-model="form.locationId" placeholder="请输入库位ID 检索条件" />
<el-form-item label="库位 检索条件" prop="locationId">
<el-input v-model="form.locationId" placeholder="请输入库位 检索条件" />
</el-form-item>
<el-form-item label="系统数量" prop="systemQuantity">
<el-input v-model="form.systemQuantity" placeholder="请输入系统数量" />
......
......@@ -51,7 +51,6 @@
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!queryParams.warehousesCode"
>
<template v-if="queryLocationName" #suffix>
<i
......@@ -238,8 +237,8 @@ export default {
this.queryParams.warehouseId = warehouse.warehouseId
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehouseId
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
......@@ -272,16 +271,16 @@ export default {
this.queryWarehouseName = null
this.queryParams.warehouseId = null
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
// this.queryLocationName = null
// this.queryParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
if (!this.queryParams.warehouseId) {
this.$message.warning("请先选择仓库")
return
}
// if (!this.queryParams.warehouseId) {
// this.$message.warning("请先选择仓库")
// return
// }
this.locationSelectorVisible = true
},
/** 清空库位选择 */
......
......@@ -76,74 +76,96 @@
@selection-change="handleSelectionChange"
border
size="small">
<el-table-column label="子表ID" align="center" width="150px" prop="id" v-if="false" />
<el-table-column label="物料" align="center" prop="materialId" width="150px" fixed>
<el-table-column label="子表" align="center" min-width="150px" prop="id" v-if="false" />
<el-table-column label="物料" align="center" prop="materialId" min-width="150px" fixed>
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
<div class="disabled-input">
{{ getDictLabel(materialDict, scope.row.materialId, 'id', 'material_name') }}
</div>
</template>
</el-table-column>
<el-table-column label="批次编号" align="center" prop="batchCode" width="150px" >
<el-table-column label="批次编号" align="center" prop="batchCode" min-width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.batchCode" placeholder="请输入批次编号" disabled />
<div class="disabled-input">
{{ scope.row.batchCode }}
</div>
</template>
</el-table-column>
<el-table-column label="仓库" align="center" prop="warehouseName" width="150px" >
<el-table-column label="仓库" align="center" prop="warehouseName" min-width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.warehouseName" placeholder="请输入仓库" disabled />
<div class="disabled-input">
{{ scope.row.warehouseName }}
</div>
</template>
</el-table-column>
<el-table-column label="库位" align="center" prop="locationName" width="150px" >
<el-table-column label="库位" align="center" prop="locationName" min-width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.locationName" placeholder="请输入库位" disabled />
<div class="disabled-input">
{{ scope.row.locationName }}
</div>
</template>
</el-table-column>
<el-table-column label="系统数量" align="center" prop="systemQuantity" width="150px" >
<el-table-column label="系统数量" align="center" prop="systemQuantity" min-width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.systemQuantity" placeholder="请输入系统数量" disabled />
<div class="disabled-input">
{{ scope.row.systemQuantity }}
</div>
</template>
</el-table-column>
<el-table-column label="实际数量" align="center" prop="actualQuantity" width="150px" >
<el-table-column label="实际数量" align="center" prop="actualQuantity" min-width="150px" >
<template slot-scope="scope">
<template v-if="isConfirm">
<div class="disabled-input">
{{ scope.row.actualQuantity }}
</div>
</template>
<template v-else>
<el-input v-model="scope.row.actualQuantity"
placeholder="请输入实际数量"
type="number"
:disabled="isConfirm"
@input="handleItemChange(scope.row)"
/>
</template>
</template>
</el-table-column>
<el-table-column label="差异数量" align="center" prop="varianceQuantity" width="150px" >
<el-table-column label="差异数量" align="center" prop="varianceQuantity" min-width="150px" >
<template slot-scope="scope">
<el-input type="number" v-model="scope.row.varianceQuantity" placeholder="请输入差异数量" disabled />
<div class="disabled-input">
{{ scope.row.varianceQuantity }}
</div>
</template>
</el-table-column>
<el-table-column label="单价" align="center" prop="unitPrice" width="150px" >
<el-table-column label="单价" align="center" prop="unitPrice" min-width="150px" >
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
<div class="disabled-input">
{{ formatAmount(scope.row.unitPrice) }}
</div>
</template>
</el-table-column>
<el-table-column label="差异金额" align="center" prop="varianceAmount" width="150px" >
<el-table-column label="差异金额" align="center" prop="varianceAmount" min-width="150px" >
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
<div class="disabled-input">
{{ formatAmount(scope.row.varianceAmount) }}
</div>
</template>
</el-table-column>
<el-table-column label="是否已调整" align="center" prop="adjusted" v-if="isConfirm" width="150px" >
<el-table-column label="是否已调整" align="center" prop="adjusted" v-if="isConfirm" min-width="150px" >
<template slot-scope="scope">
<!-- <el-input v-model="scope.row.adjusted" placeholder="请输入是否已调整0否1是" disabled />-->
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
<div class="disabled-input">
<dict-tag :options="dict.type.is_adjusted" :value="scope.row.adjusted"/>
</div>
</template>
</el-table-column>
<el-table-column prop="adjustedType" align="center" label="调整原因类型" width="150px">
<template slot-scope="scope">
<el-table-column prop="adjustedType" align="center" label="调整原因类型" min-width="150px">
<template v-if="isConfirm" slot-scope="scope">
<div
class="disabled-input"
>
{{ getAdjustReasonName(scope.row.adjustedType) }}
</div>
</template>
<template v-else slot-scope="scope">
<!-- <template slot-scope="scope"> -->
<el-select
v-model="scope.row.adjustedType"
placeholder="请选择调整原因类型"
......@@ -162,26 +184,38 @@
</el-select>
</template>
</el-table-column>
<el-table-column label="调整原因" align="center" prop="adjustmentReason" width="150px" >
<el-table-column label="调整原因" align="center" prop="adjustmentReason" min-width="150px" >
<template slot-scope="scope">
<template v-if="isConfirm">
<div
class="disabled-input"
>
{{ scope.row.adjustmentReason }}
</div>
</template>
<template v-else>
<el-input
v-model="scope.row.adjustmentReason"
placeholder="请输入调整原因"
type="text"
:disabled="isConfirm"
:style="(Number(scope.row.varianceQuantity)||0)!==0 && !scope.row.adjustmentReason ? {border:'1px solid #f56c6c',boxShadow:'0 0 0 2px rgba(245,108,108,0.2)'} : {}"
@input="handleItemChange(scope.row)"
/>
</template>
</template>
</el-table-column>
<el-table-column label="调整人" align="center" prop="adjustedBy" v-if="isConfirm" width="150px" >
<el-table-column label="调整人" align="center" prop="adjustedBy" v-if="isConfirm" min-width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.adjustedBy" placeholder="请输入调整人" disabled />
<div class="disabled-input">
{{ scope.row.adjustedBy }}
</div>
</template>
</el-table-column>
<el-table-column label="调整时间" align="center" prop="adjustedAt"v-if="isConfirm" width="150px" >
<el-table-column label="调整时间" align="center" prop="adjustedAt" v-if="isConfirm" min-width="150px" >
<template slot-scope="scope">
<el-date-picker clearable v-model="scope.row.adjustedAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择调整时间" disabled />
<div class="disabled-input">
{{ scope.row.adjustedAt }}
</div>
</template>
</el-table-column>
</el-table>
......@@ -458,6 +492,11 @@ export default {
})
// 同步通知父组件数据变化
this.$emit("item-change", row);
},
/** 获取调整原因名称 */
getAdjustReasonName(status) {
const item = this.dict.type.adjusted_type.find(item => item.value === status)
return item ? item.label : '未知'
}
}
}
......@@ -486,11 +525,12 @@ export default {
--el-table-row-hover-bg-color: #f5f7fa;
}
.disabled-input {
/* .disabled-input {
background-color: #f5f7fa !important;
border: 1px solid #e5e6eb !important;
color: #909399 !important;
cursor: not-allowed !important;
border-radius: 4px !important;
}
padding: 0 15px; height: 32px; line-height: 32px;
} */
</style>
......@@ -104,19 +104,19 @@
<div class="table-container">
<el-table v-loading="loading" :data="warehousesList" height="100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="仓库编码" align="center" prop="warehousesCode" width="120" fixed />
<el-table-column label="仓库名称" align="center" prop="warehousesName" width="150" />
<el-table-column label="仓库类型" align="center" prop="warehouseType" width="100">
<el-table-column label="仓库编码" align="center" prop="warehousesCode" min-width="120" fixed />
<el-table-column label="仓库名称" align="center" prop="warehousesName" min-width="150" />
<el-table-column label="仓库类型" align="center" prop="warehouseType" min-width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.warehouse_type" :value="scope.row.warehouseType"/>
</template>
</el-table-column>
<el-table-column label="仓库地点" align="center" prop="address" width="200" />
<el-table-column label="仓库区域" align="center" prop="area" width="120" />
<el-table-column label="仓库容量" align="center" prop="capacity" width="100" />
<el-table-column label="仓库管理员" align="center" prop="manager" width="120" />
<el-table-column label="联系电话" align="center" prop="contactPhone" width="120" />
<el-table-column label="应用状态" align="center" prop="isEnabled" width="100">
<el-table-column label="仓库地点" align="center" prop="address" min-width="200" />
<el-table-column label="仓库区域" align="center" prop="area" min-width="120" />
<el-table-column label="仓库容量" align="center" prop="capacity" min-width="100" />
<el-table-column label="仓库管理员" align="center" prop="manager" min-width="120" />
<el-table-column label="联系电话" align="center" prop="contactPhone" min-width="120" />
<el-table-column label="应用状态" align="center" prop="isEnabled" min-width="100">
<template slot-scope="scope">
<el-tag
:type="scope.row.isEnabled === 1 ? 'success' : 'danger'"
......@@ -126,7 +126,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建日期" align="center" prop="createTime" width="160" />
<el-table-column label="创建日期" align="center" prop="createTime" min-width="160" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
<template slot-scope="scope">
<el-button
......
......@@ -18,6 +18,7 @@ import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.uuid.UUID;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.inventory.domain.TO.InboundItemsTO;
import com.ruoyi.inventory.domain.vo.inboundVO.InboundFinishTemplateVO;
import com.ruoyi.inventory.domain.vo.InboundMaterialTotalVO;
import com.ruoyi.inventory.domain.vo.inboundVO.InboundTRDCTemplateVO;
......@@ -73,8 +74,21 @@ public class InboundOrdersController extends BaseController
public void export(HttpServletResponse response, InboundOrders inboundOrders)
{
List<InboundOrders> list = inboundOrdersService.selectInboundOrdersList(inboundOrders);
// for (InboundOrders inboundItem : list) {
// if (inboundOrders.getOrderStatus() == 1) {
// InboundItemsTO inboundItemsTO = new InboundItemsTO();
// inboundItemsTO.setRelocationId(inboundItem.getL)
// }else if (inboundOrders.getOrderStatus() == 2) {
//
// }else if (inboundOrders.getOrderStatus() == 3) {
//
// }else{
//
// }
// }
ExcelUtil<InboundOrders> util = new ExcelUtil<InboundOrders>(InboundOrders.class);
util.exportExcel(response, list, "入库单数据");
util.exportExcel(response, list, "入库单导出数据");
}
/**
......
......@@ -22,62 +22,71 @@ public class InboundOrders extends BaseEntity
private String id;
/** 入库单号 检索条件 */
@Excel(name = "入库单号 检索条件")
@Excel(name = "入库单号")
private String orderId;
/** 系统编号 检索条件 */
@Excel(name = "系统编号 检索条件")
@Excel(name = "系统编号")
private String systemNo;
/** 入库类型 字典,检索条件 */
@Excel(name = "入库类型 字典,检索条件")
@Excel(name = "入库类型")
private String orderTypeId;
/** 批次ID 检索条件 */
@Excel(name = "批次ID 检索条件")
@Excel(name = "批次")
private String batchId;
/** 仓库ID 暂无用 */
@Excel(name = "仓库ID 暂无用")
@Excel(name = "源仓库")
private String warehouseId;
private String warehouseName;
/** 货主ID */
@Excel(name = "货主ID")
@Excel(name = "货主")
private String ownerId;
private String ownerName;
/** 入库单状态1-草稿 2-已完成 3-已取消 字典,检索条件 */
@Excel(name = "入库单状态1-草稿 2-已完成 3-已取消 字典,检索条件")
@Excel(name = "入库单状态")
private Long orderStatus;
/** 入库日期 日期无时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "入库日期 日期无时间", width = 30, dateFormat = "yyyy-MM-dd")
@Excel(name = "入库日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date inboundDate;
/** 开始日期 只做查询 */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date inboundDateStart;
/** 结束日期 只做查询 */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date inboundDateEnd;
/** 订单类型 字典,检索条件 */
@Excel(name = "订单类型 字典,检索条件")
@Excel(name = "订单类型")
private String orderType;
/** 计划量 暂无用 */
@Excel(name = "计划量 暂无用")
@Excel(name = "计划量")
private Long totalPlannedQuantity;
/** 实际量 暂无用 */
@Excel(name = "实际量 暂无用")
@Excel(name = "实际量")
private Long totalActualQuantity;
/** 总件数 暂无用 */
@Excel(name = "总件数 暂无用")
@Excel(name = "总件数")
private Long totalPackages;
/** 负责人 暂无用 */
@Excel(name = "负责人 暂无用")
@Excel(name = "负责人")
private String opUserName;
/** 应用数据1使用0删除 删除用 */
@Excel(name = "应用数据1使用0删除 删除用")
@Excel(name = "应用数据")
private Long isUsed;
/** 排序 */
......@@ -293,6 +302,30 @@ public class InboundOrders extends BaseEntity
this.ownerName = ownerName;
}
public String getWarehouseName() {
return warehouseName;
}
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
public Date getInboundDateStart() {
return inboundDateStart;
}
public void setInboundDateStart(Date inboundDateStart) {
this.inboundDateStart = inboundDateStart;
}
public Date getInboundDateEnd() {
return inboundDateEnd;
}
public void setInboundDateEnd(Date inboundDateEnd) {
this.inboundDateEnd = inboundDateEnd;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
......
......@@ -180,4 +180,5 @@ public class Inventory extends BaseEntity
private String specialRequirements;
private Double unitPrice;
private String inboundOrderId;
}
......@@ -94,6 +94,6 @@ public class InventoryTransactions extends BaseEntity
private String updateUserCode;
@Excel(name = "单价")
private String unitPrice;
private Double unitPrice;
}
package com.ruoyi.inventory.domain.TO;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 入库单明细对象 inbound_order_items
*
* @author ruoyi
* @date 2025-12-02
*/
public class InboundItemsAndMaterialName extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 编号 */
private String id;
/** 入库单号 检索条件 */
@Excel(name = "入库单号")
private String orderId;
/** 入库单号 检索条件 */
@Excel(name = "主表Id")
private String inboundOrderId;
/** 货物ID 字典,检索条件 */
// @Excel(name = "货物ID")
private String materialId;
@Excel(name = "SapNo")
private String sapNo;
private String materialName;
private Double unitWeight;
/** 批次ID 检索条件 */
@Excel(name = "批次ID")
private String batchId;
/** 仓库ID 检索条件 */
@Excel(name = "仓库ID")
private String warehouseId;
private String warehousesName;
/** 库位ID 检索条件 */
@Excel(name = "库位ID")
private String locationId;
private String locationName;
/** 计划数量 */
@Excel(name = "计划数量")
private Long plannedQuantity;
/** 实际数量 */
@Excel(name = "实际数量")
private Long actualQuantity;
/** 计划件数 暂无用 */
@Excel(name = "计划件数")
private Long plannedPackages;
/** 实际件数 */
@Excel(name = "实际件数")
private Long actualPackages;
/** 约数 */
// @Excel(name = "约数")
private Long divisor;
/** 标签颜色 字典,检索条件 */
@Excel(name = "标签颜色")
private Long labelColor;
/** 凭证号 检索条件 */
@Excel(name = "凭证号")
private String voucherNumber;
/** 单价 */
@Excel(name = "单价")
private Long unitPrice;
/** 状态1-待收货 2-部分收货 3-已完成 暂无用 */
// @Excel(name = "状态")
private Long itemStatus;
/** 收货时间 暂无用 */
@Excel(name = "收货时间")
private Long receivedAt;
/** 收货人 */
@Excel(name = "收货人")
private String receivedBy;
/** 应用数据1使用0删除 删除用 */
// @Excel(name = "应用数据")
private Long isUsed;
/** 排序 */
// @Excel(name = "排序")
private Long sortNo;
/** 创建日期 */
// @Excel(name = "创建日期")
private String createUserCode;
/** 排序号 */
// @Excel(name = "排序号")
private String updateUserCode;
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 setMaterialId(String materialId)
{
this.materialId = materialId;
}
public String getMaterialId()
{
return materialId;
}
public void setBatchId(String batchId)
{
this.batchId = batchId;
}
public String getBatchId()
{
return batchId;
}
public void setWarehouseId(String warehouseId)
{
this.warehouseId = warehouseId;
}
public String getWarehouseId()
{
return warehouseId;
}
public void setLocationId(String locationId)
{
this.locationId = locationId;
}
public String getLocationId()
{
return locationId;
}
public void setPlannedQuantity(Long plannedQuantity)
{
this.plannedQuantity = plannedQuantity;
}
public Long getPlannedQuantity()
{
return plannedQuantity;
}
public void setActualQuantity(Long actualQuantity)
{
this.actualQuantity = actualQuantity;
}
public Long getActualQuantity()
{
return actualQuantity;
}
public void setPlannedPackages(Long plannedPackages)
{
this.plannedPackages = plannedPackages;
}
public Long getPlannedPackages()
{
return plannedPackages;
}
public void setActualPackages(Long actualPackages)
{
this.actualPackages = actualPackages;
}
public Long getActualPackages()
{
return actualPackages;
}
public void setDivisor(Long divisor)
{
this.divisor = divisor;
}
public Long getDivisor()
{
return divisor;
}
public void setLabelColor(Long labelColor)
{
this.labelColor = labelColor;
}
public Long getLabelColor()
{
return labelColor;
}
public void setVoucherNumber(String voucherNumber)
{
this.voucherNumber = voucherNumber;
}
public String getVoucherNumber()
{
return voucherNumber;
}
public void setUnitPrice(Long unitPrice)
{
this.unitPrice = unitPrice;
}
public Long getUnitPrice()
{
return unitPrice;
}
public void setItemStatus(Long itemStatus)
{
this.itemStatus = itemStatus;
}
public Long getItemStatus()
{
return itemStatus;
}
public void setReceivedAt(Long receivedAt)
{
this.receivedAt = receivedAt;
}
public Long getReceivedAt()
{
return receivedAt;
}
public void setReceivedBy(String receivedBy)
{
this.receivedBy = receivedBy;
}
public String getReceivedBy()
{
return receivedBy;
}
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 String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getInboundOrderId() {
return inboundOrderId;
}
public void setInboundOrderId(String inboundOrderId) {
this.inboundOrderId = inboundOrderId;
}
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 getSapNo() {
return sapNo;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public Double getUnitWeight() {
return unitWeight;
}
public void setUnitWeight(Double unitWeight) {
this.unitWeight = unitWeight;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("orderId", getOrderId())
.append("materialId", getMaterialId())
.append("batchId", getBatchId())
.append("warehouseId", getWarehouseId())
.append("locationId", getLocationId())
.append("plannedQuantity", getPlannedQuantity())
.append("actualQuantity", getActualQuantity())
.append("plannedPackages", getPlannedPackages())
.append("actualPackages", getActualPackages())
.append("divisor", getDivisor())
.append("labelColor", getLabelColor())
.append("voucherNumber", getVoucherNumber())
.append("unitPrice", getUnitPrice())
.append("itemStatus", getItemStatus())
.append("receivedAt", getReceivedAt())
.append("receivedBy", getReceivedBy())
.append("remark", getRemark())
.append("isUsed", getIsUsed())
.append("sortNo", getSortNo())
.append("createTime", getCreateTime())
.append("createUserCode", getCreateUserCode())
.append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode())
.append("materialName", getMaterialName())
.append("inboundOrderId", getInboundOrderId())
.append("warehousesName", getWarehousesName())
.append("locationName", getLocationName())
.append("sapNo", getSapNo())
.append("unitWeight", getUnitWeight())
.toString();
}
}
package com.ruoyi.inventory.domain.TO;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 入库单明细对象 inbound_order_items
*
* @author ruoyi
* @date 2025-12-02
*/
@Data
public class InboundItemsTO extends BaseEntity {
private static final long serialVersionUID = 1L;
// ======================== 匹配Excel表头的字段(按表头顺序) ========================
/** 日期 */
@Excel(name = "日期")
private String inboundDate; // 建议用LocalDateTime,若Excel是字符串格式则用String
/** SAP No */
@Excel(name = "SAP No")
private String sapNo;
/** 物料名称 */
@Excel(name = "物料名称")
private String materialName;
/** TS Code */
@Excel(name = "TS Code")
private String tsCode;
/** 批号 */
@Excel(name = "批号")
private String batchId;
/** 计划数量 */
@Excel(name = "计划数量")
private Long plannedQuantity;
/** 件重 */
@Excel(name = "件重")
private Double unitWeight;
/** 约数 */
@Excel(name = "约数")
private Long divisor;
/** 件数 */
@Excel(name = "件数")
private Long actualPackages;
/** 实发数量 */
@Excel(name = "实发数量")
private Long actualQuantity;
/** 重量 */
@Excel(name = "重量(成品)")
private Double weight;
/** 库位 */
@Excel(name = "库位")
private String locationId;
/** 仓库 */
@Excel(name = "仓库")
private String warehouseId;
/** 库位(成品) */
@Excel(name = "库位(成品)")
private String finishedLocationId;
/** 备注(TRDC) */
@Excel(name = "备注(TRDC)")
private String remarkTrdc;
/** 收货库位(正常) */
@Excel(name = "收货库位(正常)")
private String relocationId;
/** 标签颜色 */
@Excel(name = "标签颜色")
private Long labelColor;
/** 凭证号 */
@Excel(name = "凭证号")
private String voucherNumber;
/** 保温 */
@Excel(name = "保温")
private String keepWarm;
/** 危险类别 */
@Excel(name = "危险类别")
private String hazardId;
/** 单号 */
@Excel(name = "单号")
private String orderId;
/** 系统编号 */
@Excel(name = "系统编号")
private String systemNo;
/** 智观(客户订单号) */
@Excel(name = "智观(客户订单号)")
private String finishedSystemNo;
/** 客户订单号/PO号 */
@Excel(name = "客户订单号/PO号")
private String finishedOrderId;
/** 货主 */
@Excel(name = "货主")
private String ownerId;
/** 贴标数量 */
@Excel(name = "贴标数量")
private Long labelQuantity;
/** 订单类型 */
@Excel(name = "订单类型")
private Long orderType;
/** 单件重量 */
@Excel(name = "单件重量")
private Double packageWeight;
// ======================== 原有类中多的字段(放在末尾) ========================
/** 编号 */
private String id;
/** 入库单号 检索条件(主表Id) */
private String inboundOrderId;
/** 货物ID 字典,检索条件 */
private String materialId;
/** 仓库名称 */
private String warehousesName;
/** 库位名称 */
private String locationName;
/** 计划件数 暂无用 */
private Long plannedPackages;
/** 实际数量(原有) */
private Long actualQuantity1;
/** 实际件数 */
private Long actualPackages1;
/** 单价 */
private Long unitPrice;
/** 状态1-待收货 2-部分收货 3-已完成 暂无用 */
private Long itemStatus;
/** 收货时间 暂无用 */
private Long receivedAt;
/** 收货人 */
private String receivedBy;
/** 应用数据1使用0删除 删除用 */
private Long isUsed;
/** 排序 */
private Long sortNo;
/** 创建人编码 */
private String createUserCode;
/** 更新人编码 */
private String updateUserCode;
}
\ No newline at end of file
......@@ -102,7 +102,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
@Override
public int updateInboundOrders(InboundOrders inboundOrders)
{
inboundOrdersMapper.deleteInboundOrderItemsByOrderId(inboundOrders.getOrderId());
inboundOrdersMapper.deleteInboundOrderItemsByOrderId(inboundOrders.getId());
inboundOrders.setUpdateTime(DateUtils.getNowDate());
inboundOrders.setUpdateUserCode(SystemUtils.getUserName());
inboundOrders.setUpdateBy(SystemUtils.getUserName());
......
......@@ -11,6 +11,7 @@ import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.vo.InventoryExceedWarnVO;
import com.ruoyi.inventory.domain.vo.InventorySummaryVO;
import com.ruoyi.inventory.domain.vo.InventoryVo;
import com.ruoyi.inventory.mapper.InboundOrdersMapper;
import com.ruoyi.inventory.mapper.OutboundOrderItemsMapper;
import com.ruoyi.inventory.mapper.OutboundOrderLogMapper;
import org.apache.commons.collections4.CollectionUtils;
......@@ -39,6 +40,8 @@ public class InventoryServiceImpl implements IInventoryService
private OutboundOrdersServiceImpl outboundOrderMapper;
@Autowired
private InventoryTransactionsServiceImpl insertInventoryTransactions;
@Autowired
private InboundOrdersMapper inboundOrdersMapper;
......@@ -90,6 +93,12 @@ public class InventoryServiceImpl implements IInventoryService
return inventoryMapper.insertInventory(inventory);
}
/**
* 批量库存
*
* @param inventoryList 库存
* @return 结果
*/
@Override
public int insertInventoryList(List<Inventory> inventoryList) {
int count = 0;
......@@ -99,10 +108,12 @@ public class InventoryServiceImpl implements IInventoryService
inventory.setId(UUID.randomUUID().toString());
inventory.setCreateBy(SystemUtils.getUserName());
inventory.setCreateUserCode(SystemUtils.getUserName());
createInventoryInboundLog(inventory,inventory.getQuantity(),inventory.getCreateUserCode(),inventory.getCreateTime());
count = inventoryMapper.insertInventory(inventory);
}
return count;
}
/**
* 修改库存
*
......@@ -134,7 +145,6 @@ public class InventoryServiceImpl implements IInventoryService
Inventory inventory = new Inventory();
inventory.setLockedQuantity(lockedQuantity);
inventory.setId(inventoryId);
inventoryMapper.updateInventory(inventory);
}
return 1;
......@@ -170,7 +180,7 @@ public class InventoryServiceImpl implements IInventoryService
transactions.setId(IdUtils.simpleUUID()); // 确保IdUtils工具类存在,若无则替换为UUID.randomUUID().toString()
transactions.setTransactionType(2L); // 事务类型-出库
transactions.setBatchCode(outboundOrderItem.getBatchCode());
transactions.setUnitPrice(String.valueOf(outboundOrderItem.getUnitPrice()));
transactions.setUnitPrice(outboundOrderItem.getUnitPrice());
transactions.setInventoryId(inventory.getId()); // 库存表Id
transactions.setReferenceId(outboundOrderItem.getOutboundOrderId()); // 关联出库单主表ID
transactions.setReferenceItemId(outboundOrderItem.getId()); // 关联出库单明细ID
......@@ -196,6 +206,39 @@ public class InventoryServiceImpl implements IInventoryService
insertInventoryTransactions.insertInventoryTransactions(transactions);
}
//入库单确认入库日志
private void createInventoryInboundLog(Inventory inventory,
Long addQty, String createUser, Date createTime) {
InventoryTransactions transactions = new InventoryTransactions();
transactions.setId(IdUtils.simpleUUID()); // 确保IdUtils工具类存在,若无则替换为UUID.randomUUID().toString()
transactions.setTransactionType(1L); // 事务类型-入库
transactions.setBatchCode(inventory.getBatchId());
transactions.setUnitPrice(inventory.getUnitPrice());
transactions.setInventoryId(inventory.getId()); // 库存表Id
transactions.setReferenceId(inventory.getInboundOrderId()); // 关联出库单主表ID
transactions.setReferenceItemId(inventory.getId()); // 关联出库单明细ID
transactions.setMaterialId(inventory.getMaterialId());
transactions.setWarehouseId(inventory.getWarehousesId());
transactions.setLocationId(inventory.getLocationId());
transactions.setOwnerId(inventory.getOwnerId());
// 新建实体,查看该物料在库存中数量,避免其他条件干扰
Inventory inventoryBefore = new Inventory();
inventoryBefore.setMaterialId(inventory.getMaterialId());
inventoryBefore = inventoryMapper.selectInventory(inventoryBefore);
if (inventoryBefore == null) {
inventoryBefore = new Inventory();
inventoryBefore.setQuantity(0L);
}
transactions.setQuantityBefore(inventoryBefore.getQuantity());
transactions.setQuantityAfter(inventory.getQuantity() + addQty);
transactions.setQuantityChange(addQty);
transactions.setTransactionTime(createTime);
transactions.setOperatedBy(createUser);
// 插入日志
insertInventoryTransactions.insertInventoryTransactions(transactions);
}
@SerialExecution(group = "inventoryRefresh", fair = true)
@Override
......
......@@ -71,7 +71,7 @@
</select>
<resultMap type="com.ruoyi.inventory.domain.TO.InboundItemsAndMaterialName" id="InboundOrderItemsAndMnameResult">
<resultMap type="com.ruoyi.inventory.domain.TO.InboundItemsTO" id="InboundOrderItemsAndMnameResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id" />
......
......@@ -33,7 +33,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<collection property="inboundOrderItemsList" ofType="InboundOrderItems" column="id" select="selectInboundOrderItemsList" />
</resultMap>
<resultMap type="com.ruoyi.inventory.domain.TO.InboundItemsAndMaterialName" id="InboundOrderItemsResult">
<resultMap type="com.ruoyi.inventory.domain.TO.InboundItemsTO" id="InboundOrderItemsResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id"/>
......@@ -82,7 +82,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="warehouseId != null and warehouseId != ''"> and warehouse_id = #{warehouseId}</if>
<if test="ownerId != null and ownerId != ''"> and owner_id = #{ownerId}</if>
<if test="orderStatus != null "> and order_status = #{orderStatus}</if>
<if test="inboundDate != null "> and inbound_date = #{inboundDate}</if>
<!-- 新增按照日期范围查询-->
<if test="inboundDateStart != null">
AND inbound_date &gt;= #{inboundDateStart}
</if>
<if test="inboundDateEnd != null">
AND inbound_date &lt;= #{inboundDateEnd}
</if>
<if test="orderType != null and orderType != ''"> and order_type = #{orderType}</if>
<if test="totalPlannedQuantity != null "> and total_planned_quantity = #{totalPlannedQuantity}</if>
<if test="totalActualQuantity != null "> and total_actual_quantity = #{totalActualQuantity}</if>
......@@ -215,13 +221,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<delete id="deleteInboundOrderItemsByOrderIds" parameterType="String">
delete from inbound_order_items where inbound_order_id in
<foreach item="orderId" collection="array" open="(" separator="," close=")">
#{orderId}
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<delete id="deleteInboundOrderItemsByOrderId" parameterType="String">
delete from inbound_order_items where order_id = #{orderId}
delete from inbound_order_items where inbound_order_id = #{id}
</delete>
<insert id="batchInboundOrderItems">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论