Commit 59df6518 by zhangtw

入库导入

parent 02e541a7
...@@ -35,6 +35,15 @@ ...@@ -35,6 +35,15 @@
<el-button <el-button
type="warning" type="warning"
plain 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" icon="el-icon-download"
size="medium" size="medium"
@click="handleExport" @click="handleExport"
...@@ -292,7 +301,7 @@ ...@@ -292,7 +301,7 @@
ref="inboundItemsRef" ref="inboundItemsRef"
v-model="form.inboundOrderItemsList" v-model="form.inboundOrderItemsList"
:embedded="true" :embedded="true"
:order-id="orderId" :inboundOrderId="inboundOrderId"
:show-search-form="false" :show-search-form="false"
:show-pagination="false" :show-pagination="false"
:show-toolbar="true" :show-toolbar="true"
...@@ -356,7 +365,7 @@ ...@@ -356,7 +365,7 @@
ref="detailItemsRef" ref="detailItemsRef"
v-model="detailForm.inboundOrderItemsList" v-model="detailForm.inboundOrderItemsList"
:embedded="true" :embedded="true"
:order-id="detailForm.orderId" :inboundOrderId="detailForm.inboundOrderId"
:isEditable="isEditable" :isEditable="isEditable"
:show-search-form="false" :show-search-form="false"
:show-pagination="false" :show-pagination="false"
...@@ -386,6 +395,16 @@ ...@@ -386,6 +395,16 @@
<el-button type="primary" @click="confirmMaterialSelect">确定</el-button> <el-button type="primary" @click="confirmMaterialSelect">确定</el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 导入弹窗 -->
<import-excel
ref="import"
title="导入"
import-url="/inventory/inbound/import"
template-url="/inventory/inbound/importTemplate"
template-name="入库单导入模板"
@success="getList"
/>
</div> </div>
</template> </template>
...@@ -397,6 +416,7 @@ import InboundItems from "@/views/inventory/inbound_items/index.vue" ...@@ -397,6 +416,7 @@ import InboundItems from "@/views/inventory/inbound_items/index.vue"
import PageTitle from "@/components/PageTitle" // 引入字典页面的标题组件 import PageTitle from "@/components/PageTitle" // 引入字典页面的标题组件
import PageWrapperSearch from "@/components/Search/PageWrapperSearch" // 引入搜索包装组件 import PageWrapperSearch from "@/components/Search/PageWrapperSearch" // 引入搜索包装组件
import MaterialSelector from "@/views/inventory/materials/materialsSeletor.vue"; import MaterialSelector from "@/views/inventory/materials/materialsSeletor.vue";
import ImportExcel from "@/components/ImportExcel/index"
export default { export default {
name: "Inbound", name: "Inbound",
...@@ -404,7 +424,8 @@ export default { ...@@ -404,7 +424,8 @@ export default {
InboundItems, InboundItems,
PageTitle, PageTitle,
PageWrapperSearch, PageWrapperSearch,
MaterialSelector MaterialSelector,
ImportExcel
}, },
data() { data() {
return { return {
...@@ -431,7 +452,7 @@ export default { ...@@ -431,7 +452,7 @@ export default {
detailOpen: false, detailOpen: false,
detailForm: {}, // 新增详情表单数据 detailForm: {}, // 新增详情表单数据
// 组件监听修改时的orderId变化 // 组件监听修改时的orderId变化
orderId: null, inboundOrderId: null,
// 选中的明细项 // 选中的明细项
selectedItems: [], selectedItems: [],
// 遮罩层 // 遮罩层
...@@ -588,11 +609,10 @@ export default { ...@@ -588,11 +609,10 @@ export default {
const id = row.id const id = row.id
getInbound(id).then(response => { getInbound(id).then(response => {
this.form = response.data this.form = response.data
this.orderId = response.data.orderId
// 加载明细数据 // 加载明细数据
if (this.$refs.inboundItemsRef) { this.inboundOrderId = id
this.$refs.inboundItemsRef.loadRelatedData(this.orderId) this.$nextTick(() => {
} })
this.open = true this.open = true
this.title = "修改入库单" this.title = "修改入库单"
}) })
...@@ -600,14 +620,12 @@ export default { ...@@ -600,14 +620,12 @@ export default {
/** 查看详情 */ /** 查看详情 */
handleDetail(row) { handleDetail(row) {
this.reset() this.reset()
const id = row.id || this.ids const id = row.id
this.isEditable = false this.isEditable = false
getInbound(id).then(response => { getInbound(id).then(response => {
this.detailForm = response.data
// 加载明细数据到详情 // 加载明细数据到详情
if (this.$refs.detailItemsRef) { this.detailForm = response.data
this.$refs.detailItemsRef.loadRelatedData(this.detailForm.orderId) this.detailForm.inboundOrderId = id
}
this.detailOpen = true this.detailOpen = true
}) })
}, },
...@@ -651,7 +669,6 @@ export default { ...@@ -651,7 +669,6 @@ export default {
}); });
} }
}); });
console.log(this.form.inboundOrderItemsList)
this.materialSelectOpen = false; this.materialSelectOpen = false;
this.$refs.inboundItemsRef.handleAddItem(this.selectedMaterials) this.$refs.inboundItemsRef.handleAddItem(this.selectedMaterials)
this.$message.success(`成功添加 ${this.selectedMaterials.length} 个物料`); this.$message.success(`成功添加 ${this.selectedMaterials.length} 个物料`);
...@@ -797,7 +814,10 @@ export default { ...@@ -797,7 +814,10 @@ export default {
this.$refs.form.resetFields() this.$refs.form.resetFields()
} }
}, },
/** 导入按钮操作 */
handleImport() {
this.$refs.import.show()
},
/** 处理明细项选择变化 */ /** 处理明细项选择变化 */
handleItemsSelectionChange(selection) { handleItemsSelectionChange(selection) {
this.selectedItems = selection this.selectedItems = selection
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
@click="handleBatchDelete" @click="handleBatchDelete"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5" v-if="isEditable"> <!-- <el-col :span="1.5" v-if="isEditable">
<el-button <el-button
type="warning" type="warning"
plain plain
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
@click="handleImport" @click="handleImport"
v-hasPermi="['inventory:inbound_items:import']" v-hasPermi="['inventory:inbound_items:import']"
>导入</el-button> >导入</el-button>
</el-col> </el-col> -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="warning" type="warning"
...@@ -282,7 +282,7 @@ export default { ...@@ -282,7 +282,7 @@ export default {
default: true default: true
}, },
// 主表ID // 主表ID
orderId: { inboundOrderId: {
type: [String, Number], type: [String, Number],
default: null default: null
}, },
...@@ -329,13 +329,13 @@ export default { ...@@ -329,13 +329,13 @@ export default {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
materialId: null, materialId: null,
inboundOrderId: null,
warehouseId: null, warehouseId: null,
locationId: null, locationId: null,
labelColor: null, labelColor: null,
voucherNumber: null, voucherNumber: null,
receivedBy: null, receivedBy: null,
pageSize: this.pageSize, pageSize: this.pageSize
orderId: this.orderId
}, },
cachedData: [] cachedData: []
} }
...@@ -386,13 +386,15 @@ export default { ...@@ -386,13 +386,15 @@ export default {
this.syncDataToParent() this.syncDataToParent()
} }
}, },
orderId: { inboundOrderId: {
immediate: true, immediate: true,
handler(newVal) { handler(newVal) {
this.queryParams.orderId = newVal console.log('inboundOrderId 变化:', newVal)
// 核心:过滤 null/空值,只在有效时执行逻辑
if (!newVal) return
this.loadRelatedData(newVal) this.loadRelatedData(newVal)
this.displayData.forEach(item => { this.displayData.forEach(item => {
if (!item.orderId) item.orderId = newVal if (!item.inboundOrderId) item.inboundOrderId = newVal
}) })
} }
}, },
...@@ -437,10 +439,10 @@ export default { ...@@ -437,10 +439,10 @@ export default {
}, },
// 加载关联数据 // 加载关联数据
loadRelatedData(orderId) { loadRelatedData(inboundOrderId) {
if (!orderId) return if (!inboundOrderId) return
this.loading = true this.loading = true
this.queryParams.inboundOrderId = inboundOrderId
listInbound_itemsAndMname(this.queryParams).then(response => { listInbound_itemsAndMname(this.queryParams).then(response => {
this.displayData = response.rows.map(item => ({ this.displayData = response.rows.map(item => ({
...item, ...item,
......
...@@ -141,31 +141,31 @@ ...@@ -141,31 +141,31 @@
<!-- 表格列保持不变 --> <!-- 表格列保持不变 -->
<el-table-column type="selection" width="55" align="center" fixed/> <el-table-column type="selection" width="55" align="center" fixed/>
<el-table-column type="index" label="序号" align="center"/> <el-table-column type="index" label="序号" align="center"/>
<el-table-column label="SAP物料号" align="center" prop="sapNo" /> <el-table-column label="SAP物料号" align="center" prop="sapNo" width="150"/>
<!-- <el-table-column label="物料编码" align="center" prop="materialCode" width="120"/> --> <!-- <el-table-column label="物料编码" align="center" prop="materialCode" width="120"/> -->
<el-table-column label="物料名称" align="center" prop="materialName" width="150"/> <el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="TS Code" align="center" prop="tsCode" /> <el-table-column label="TS Code" align="center" prop="tsCode" width="150"/>
<el-table-column label="物料分类" align="center" prop="categoryCode" > <el-table-column label="物料分类" align="center" prop="categoryCode" >
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.displayCategory || categoryMap[scope.row.categoryCode] || scope.row.categoryCode }} {{ scope.row.displayCategory || categoryMap[scope.row.categoryCode] || scope.row.categoryCode }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="危险类别ID" align="center" prop="hazardId" /> <el-table-column label="危险类别ID" align="center" prop="hazardId" width="150"/>
<el-table-column label="规格型号" align="center" prop="specification" /> <el-table-column label="规格型号" align="center" prop="specification" />
<el-table-column label="计量单位" align="center" prop="materialUnit" /> <el-table-column label="计量单位" align="center" prop="materialUnit" />
<el-table-column label="单位重量" align="center" prop="unitWeight" /> <el-table-column label="单位重量" align="center" prop="unitWeight" />
<el-table-column label="包装重量" align="center" prop="packageWeight" /> <el-table-column label="包装重量" align="center" prop="packageWeight" />
<el-table-column label="总重量" align="center" prop="totalWeight" /> <el-table-column label="总重量" align="center" prop="totalWeight" />
<el-table-column label="体积" align="center" prop="volume" /> <el-table-column label="体积" align="center" prop="volume" />
<el-table-column label="保质期天数" align="center" prop="shelfLifeDays" /> <el-table-column label="保质期天数" align="center" prop="shelfLifeDays" width="120"/>
<el-table-column label="存储温度要求" align="center" prop="storageTemperature" /> <el-table-column label="存储温度要求" align="center" prop="storageTemperature" width="120"/>
<el-table-column label="特殊存储要求" align="center" prop="specialRequirements" /> <el-table-column label="特殊存储要求" align="center" prop="specialRequirements" width="120"/>
<el-table-column label="是否批次管理" align="center" prop="isBatchManaged"> <el-table-column label="是否批次管理" align="center" prop="isBatchManaged" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}</el-tag> <el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否序列号管理" align="center" prop="isSerialManaged"> <el-table-column label="是否序列号管理" align="center" prop="isSerialManaged" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isSerialManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isSerialManaged === 1 ? '是' : '否' }}</el-tag> <el-tag :type="scope.row.isSerialManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isSerialManaged === 1 ? '是' : '否' }}</el-tag>
</template> </template>
...@@ -438,7 +438,7 @@ export default { ...@@ -438,7 +438,7 @@ export default {
// 表单校验 // 表单校验
rules: { rules: {
materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }], // materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }],
materialName: [{ required: true, message: '请输入物料名称', trigger: 'blur' }], materialName: [{ required: true, message: '请输入物料名称', trigger: 'blur' }],
sapNo: [{ required: true, message: '请输入SAP物料号', trigger: 'blur' }], sapNo: [{ required: true, message: '请输入SAP物料号', trigger: 'blur' }],
tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }] tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }]
......
...@@ -116,6 +116,7 @@ public class InboundOrderItemsController extends BaseController ...@@ -116,6 +116,7 @@ public class InboundOrderItemsController extends BaseController
{ {
return toAjax(inboundOrderItemsService.deleteInboundOrderItemsByIds(ids)); return toAjax(inboundOrderItemsService.deleteInboundOrderItemsByIds(ids));
} }
/** /**
* 导入入库单物料明细 * 导入入库单物料明细
*/ */
......
package com.ruoyi.web.controller.inventory; package com.ruoyi.web.controller.inventory;
import java.util.List; import java.util.List;
import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.utils.uuid.UUID; import com.ruoyi.common.utils.uuid.UUID;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.ruoyi.inventory.domain.InboundOrderItems;
import com.ruoyi.inventory.domain.vo.InboundTemplateVO;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
...@@ -21,6 +26,7 @@ import com.ruoyi.inventory.domain.InboundOrders; ...@@ -21,6 +26,7 @@ import com.ruoyi.inventory.domain.InboundOrders;
import com.ruoyi.inventory.service.IInboundOrdersService; import com.ruoyi.inventory.service.IInboundOrdersService;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/** /**
* 入库单主Controller * 入库单主Controller
...@@ -103,4 +109,31 @@ public class InboundOrdersController extends BaseController ...@@ -103,4 +109,31 @@ public class InboundOrdersController extends BaseController
{ {
return toAjax(inboundOrdersService.deleteInboundOrdersByIds(ids)); return toAjax(inboundOrdersService.deleteInboundOrdersByIds(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<InboundTemplateVO> util = new ExcelUtil<InboundTemplateVO>(InboundTemplateVO.class);
List<InboundTemplateVO> inboundOrders = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = inboundOrdersService.importInboundOrders(inboundOrders, updateSupport, operName);
return success(message);
}
} }
...@@ -111,12 +111,18 @@ public class MaterialsController extends BaseController ...@@ -111,12 +111,18 @@ public class MaterialsController extends BaseController
return toAjax(materialsService.deleteMaterialsByIds(ids)); return toAjax(materialsService.deleteMaterialsByIds(ids));
} }
/**
* 下载物料导入模板
*/
@PreAuthorize("@ss.hasPermi('inventory:materials:importTemplate')")
@Log(title = "物料", businessType = BusinessType.IMPORT)
@PostMapping("/importTemplate") @PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) public void importTemplate(HttpServletResponse response)
{ {
ExcelUtil<Materials> util = new ExcelUtil<Materials>(Materials.class); ExcelUtil<Materials> util = new ExcelUtil<Materials>(Materials.class);
util.importTemplateExcel(response, "物料信息"); util.importTemplateExcel(response, "物料信息");
} }
/** /**
* 导入物料 * 导入物料
*/ */
......
...@@ -18,6 +18,9 @@ public class InboundOrderItems extends BaseEntity ...@@ -18,6 +18,9 @@ public class InboundOrderItems extends BaseEntity
/** 编号 */ /** 编号 */
private String id; private String id;
/** 关联主表ID */
private String inboundOrderId;
/** 入库单号 检索条件 */ /** 入库单号 检索条件 */
@Excel(name = "入库单号") @Excel(name = "入库单号")
private String orderId; private String orderId;
...@@ -308,6 +311,14 @@ public class InboundOrderItems extends BaseEntity ...@@ -308,6 +311,14 @@ public class InboundOrderItems extends BaseEntity
return updateUserCode; return updateUserCode;
} }
public String getInboundOrderId() {
return inboundOrderId;
}
public void setInboundOrderId(String inboundOrderId) {
this.inboundOrderId = inboundOrderId;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
...@@ -335,6 +346,7 @@ public class InboundOrderItems extends BaseEntity ...@@ -335,6 +346,7 @@ public class InboundOrderItems extends BaseEntity
.append("createUserCode", getCreateUserCode()) .append("createUserCode", getCreateUserCode())
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode()) .append("updateUserCode", getUpdateUserCode())
.append("inboundOrderId", getInboundOrderId())
.toString(); .toString();
} }
} }
...@@ -22,6 +22,10 @@ public class InboundItemsAndMaterialName extends BaseEntity ...@@ -22,6 +22,10 @@ public class InboundItemsAndMaterialName extends BaseEntity
@Excel(name = "入库单号") @Excel(name = "入库单号")
private String orderId; private String orderId;
/** 入库单号 检索条件 */
@Excel(name = "主表Id")
private String inboundOrderId;
/** 货物ID 字典,检索条件 */ /** 货物ID 字典,检索条件 */
@Excel(name = "货物ID") @Excel(name = "货物ID")
private String materialId; private String materialId;
...@@ -318,6 +322,14 @@ public class InboundItemsAndMaterialName extends BaseEntity ...@@ -318,6 +322,14 @@ public class InboundItemsAndMaterialName extends BaseEntity
this.materialName = materialName; this.materialName = materialName;
} }
public String getInboundOrderId() {
return inboundOrderId;
}
public void setInboundOrderId(String inboundOrderId) {
this.inboundOrderId = inboundOrderId;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
...@@ -346,6 +358,7 @@ public class InboundItemsAndMaterialName extends BaseEntity ...@@ -346,6 +358,7 @@ public class InboundItemsAndMaterialName extends BaseEntity
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.append("updateUserCode", getUpdateUserCode()) .append("updateUserCode", getUpdateUserCode())
.append("materialName", getMaterialName()) .append("materialName", getMaterialName())
.append("inboundOrderId", getInboundOrderId())
.toString(); .toString();
} }
} }
package com.ruoyi.inventory.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.Date;
/**
* 入库单导入对象 inboundTemplate
*
* @author ruoyi
* @date 2025-12-02
*/
public class InboundTemplateVO 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")
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号")
private String sapNo;
/** 货物ID 字典,检索条件 */
@Excel(name = "货物名称")
private String materialName;
/** 负责人 暂无用 */
// @Excel(name = "负责人 暂无用")
private String opUserName;
/** 计划数量 */
@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;
/** 收货人 */
@Excel(name = "收货人")
private String receivedBy;
/** 物料备注 */
@Excel(name = "物料备注")
private String remark2;
/** 排序号 */
private Long sortNo;
/** 创建日期 */
private String createUserCode;
private String updateUserCode;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getSystemNo() {
return systemNo;
}
public void setSystemNo(String systemNo) {
this.systemNo = systemNo;
}
public String getOrderTypeId() {
return orderTypeId;
}
public void setOrderTypeId(String orderTypeId) {
this.orderTypeId = orderTypeId;
}
public String getBatchId() {
return batchId;
}
public void setBatchId(String batchId) {
this.batchId = batchId;
}
public Date getInboundDate() {
return inboundDate;
}
public void setInboundDate(Date inboundDate) {
this.inboundDate = inboundDate;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getOwnerId() {
return ownerId;
}
public void setOwnerId(String ownerId) {
this.ownerId = ownerId;
}
public String getWarehouseId() {
return warehouseId;
}
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
}
public String getRemark2() {
return remark2;
}
public void setRemark2(String remark2) {
this.remark2 = remark2;
}
public String getSapNo() {
return sapNo;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getOpUserName() {
return opUserName;
}
public void setOpUserName(String opUserName) {
this.opUserName = opUserName;
}
public Long getPlannedQuantity() {
return plannedQuantity;
}
public void setPlannedQuantity(Long plannedQuantity) {
this.plannedQuantity = plannedQuantity;
}
public Long getActualQuantity() {
return actualQuantity;
}
public void setActualQuantity(Long actualQuantity) {
this.actualQuantity = actualQuantity;
}
public Long getPlannedPackages() {
return plannedPackages;
}
public void setPlannedPackages(Long plannedPackages) {
this.plannedPackages = plannedPackages;
}
public Long getActualPackages() {
return actualPackages;
}
public void setActualPackages(Long actualPackages) {
this.actualPackages = actualPackages;
}
public Long getDivisor() {
return divisor;
}
public void setDivisor(Long divisor) {
this.divisor = divisor;
}
public Long getLabelColor() {
return labelColor;
}
public void setLabelColor(Long labelColor) {
this.labelColor = labelColor;
}
public String getVoucherNumber() {
return voucherNumber;
}
public void setVoucherNumber(String voucherNumber) {
this.voucherNumber = voucherNumber;
}
public Long getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Long unitPrice) {
this.unitPrice = unitPrice;
}
public String getReceivedBy() {
return receivedBy;
}
public void setReceivedBy(String receivedBy) {
this.receivedBy = receivedBy;
}
public String getCreateUserCode() {
return createUserCode;
}
public void setCreateUserCode(String createUserCode) {
this.createUserCode = createUserCode;
}
public String getUpdateUserCode() {
return updateUserCode;
}
public void setUpdateUserCode(String updateUserCode) {
this.updateUserCode = updateUserCode;
}
public Long getSortNo() {
return sortNo;
}
public void setSortNo(Long sortNo) {
this.sortNo = sortNo;
}
@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 + '\'' +
'}';
}
}
...@@ -29,6 +29,13 @@ public interface InboundOrdersMapper ...@@ -29,6 +29,13 @@ public interface InboundOrdersMapper
public List<InboundOrders> selectInboundOrdersList(InboundOrders inboundOrders); public List<InboundOrders> selectInboundOrdersList(InboundOrders inboundOrders);
/** /**
* 查询入库单号
*
* @param orderId 入库单主
* @return 入库单主集合
*/
public InboundOrders selectInboundOrdersByOrderId(String orderId);
/**
* 新增入库单主 * 新增入库单主
* *
* @param inboundOrders 入库单主 * @param inboundOrders 入库单主
......
package com.ruoyi.inventory.service; package com.ruoyi.inventory.service;
import java.util.List; import java.util.List;
import com.ruoyi.inventory.domain.InboundOrderItems;
import com.ruoyi.inventory.domain.InboundOrders; import com.ruoyi.inventory.domain.InboundOrders;
import com.ruoyi.inventory.domain.vo.InboundTemplateVO;
/** /**
* 入库单主Service接口 * 入库单主Service接口
...@@ -58,4 +61,12 @@ public interface IInboundOrdersService ...@@ -58,4 +61,12 @@ public interface IInboundOrdersService
* @return 结果 * @return 结果
*/ */
public int deleteInboundOrdersById(String id); public int deleteInboundOrdersById(String id);
/**
* 导入入库单明细信息
*
* @param inboundOrders,isUpdateSupport,operName 入库单数据信息
* @return 结果
*/
public String importInboundOrders(List<InboundTemplateVO> inboundOrders, Boolean isUpdateSupport, String operName);
} }
package com.ruoyi.inventory.service.impl; package com.ruoyi.inventory.service.impl;
import java.util.List; import java.util.*;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.inventory.domain.vo.InboundTemplateVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.UUID;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.inventory.domain.InboundOrderItems; import com.ruoyi.inventory.domain.InboundOrderItems;
...@@ -25,7 +31,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService ...@@ -25,7 +31,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
{ {
@Autowired @Autowired
private InboundOrdersMapper inboundOrdersMapper; private InboundOrdersMapper inboundOrdersMapper;
private static final Logger log = LoggerFactory.getLogger(InboundOrdersServiceImpl.class);
/** /**
* 查询入库单主 * 查询入库单主
* *
...@@ -135,4 +141,154 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService ...@@ -135,4 +141,154 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
} }
} }
} }
/**
* 导入入库单明细信息
*
* @param inboundOrdersList,isUpdateSupport,operName 入库单数据信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String importInboundOrders(List<InboundTemplateVO> 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<InboundTemplateVO>> orderGroupMap = inboundOrdersList.stream()
.filter(vo -> StringUtils.isNotBlank(vo.getOrderId())) // 过滤无入库单号的无效行
.collect(Collectors.groupingBy(InboundTemplateVO::getOrderId));
// 4. 遍历每个入库单分组处理
for (Map.Entry<String, List<InboundTemplateVO>> entry : orderGroupMap.entrySet()) {
String orderId = entry.getKey();
List<InboundTemplateVO> voList = entry.getValue();
InboundOrders mainDO = null;
List<InboundOrderItems> itemDOList = new ArrayList<>();
try {
// 4.1 处理主表(每个入库单号只处理一次主表)
InboundTemplateVO firstVO = voList.get(0); // 取第一条VO的主表信息
// 检查入库单是否已存在
InboundOrders existMain = inboundOrdersMapper.selectInboundOrdersByOrderId(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);
// 更新主表
inboundOrdersMapper.updateInboundOrders(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已更新;\n", orderId));
} else {
// 新增主表
mainDO = new InboundOrders();
// 复制主表字段(只复制主表相关字段,避免物料字段污染)
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.getOrderStatus() == null) {
mainDO.setOrderStatus(1L); // 默认草稿状态
}
// 插入主表
inboundOrdersMapper.insertInboundOrders(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已新增;\n", orderId));
}
// 4.2 处理子表明细(每条VO对应一条明细)
for (InboundTemplateVO vo : voList) {
InboundOrderItems itemDO = new InboundOrderItems();
// 复制子表字段(物料相关)
BeanUtils.copyProperties(vo, itemDO,
"orderId", "systemNo", "orderTypeId", "batchId"); // 排除主表字段
// 填充明细必填字段
itemDO.setId(UUID.randomUUID().toString());
itemDO.setMaterialId(vo.getSapNo());
itemDO.setOrderId(orderId); // 关联入库单号
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 = inboundOrdersMapper.batchInboundOrderItems(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()));
// 打印异常栈,方便调试
log.error("导入入库单【{}】失败", orderId, e);
}
}
// 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;
}
}
} }
...@@ -29,17 +29,19 @@ ...@@ -29,17 +29,19 @@
<result property="createUserCode" column="create_user_code" /> <result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" /> <result property="updateUserCode" column="update_user_code" />
<result property="inboundOrderId" column="inbound_order_id" />
</resultMap> </resultMap>
<sql id="selectInboundOrderItemsVo"> <sql id="selectInboundOrderItemsVo">
select id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from inbound_order_items select id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code,inbound_order_id from inbound_order_items
</sql> </sql>
<select id="selectInboundOrderItemsList" parameterType="InboundOrderItems" resultMap="InboundOrderItemsResult"> <select id="selectInboundOrderItemsList" parameterType="InboundOrderItems" resultMap="InboundOrderItemsResult">
<include refid="selectInboundOrderItemsVo"/> <include refid="selectInboundOrderItemsVo"/>
<where> <where>
<if test="inboundOrderId != null and inboundOrderId != ''"> and inbound_order_id = #{inboundOrderId}</if>
<if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if> <if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if>
<if test="materialId != null and materialId != ''"> and material_id = #{materialId}</if> <if test="materialId != null and materialId != ''"> and material_id = #{materialId}</if>
<if test="batchId != null and batchId != ''"> and batch_id = #{batchId}</if> <if test="batchId != null and batchId != ''"> and batch_id = #{batchId}</if>
...@@ -96,11 +98,15 @@ ...@@ -96,11 +98,15 @@
ii.create_user_code, ii.create_user_code,
ii.update_time, ii.update_time,
ii.update_user_code, ii.update_user_code,
ii.inbound_order_id,
m.material_name m.material_name
FROM inbound_order_items ii FROM inbound_order_items ii
LEFT JOIN materials m ON ii.material_id = m.sap_no LEFT JOIN materials m ON ii.material_id = m.sap_no
<where> <where>
<!-- 移除条件前的and,<where>标签会自动处理首个条件的and/or --> <!-- 移除条件前的and,<where>标签会自动处理首个条件的and/or -->
<if test="inboundOrderId != null and inboundOrderId != ''">
and inbound_order_id = #{inboundOrderId}
</if>
<if test="orderId != null and orderId != ''"> <if test="orderId != null and orderId != ''">
order_id = #{orderId} order_id = #{orderId}
</if> </if>
...@@ -161,6 +167,7 @@ ...@@ -161,6 +167,7 @@
<if test="updateUserCode != null and updateUserCode != ''"> <if test="updateUserCode != null and updateUserCode != ''">
and update_user_code = #{updateUserCode} and update_user_code = #{updateUserCode}
</if> </if>
</where> </where>
</select> </select>
...@@ -191,6 +198,7 @@ ...@@ -191,6 +198,7 @@
<if test="createUserCode != null">create_user_code,</if> <if test="createUserCode != null">create_user_code,</if>
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
<if test="updateUserCode != null">update_user_code,</if> <if test="updateUserCode != null">update_user_code,</if>
<if test="inboundOrderId != null">inbound_order_id,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if> <if test="id != null">#{id},</if>
...@@ -217,6 +225,7 @@ ...@@ -217,6 +225,7 @@
<if test="createUserCode != null">#{createUserCode},</if> <if test="createUserCode != null">#{createUserCode},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
<if test="updateUserCode != null">#{updateUserCode},</if> <if test="updateUserCode != null">#{updateUserCode},</if>
<if test="inboundOrderId != null">#{inboundOrderId},</if>
</trim> </trim>
</insert> </insert>
...@@ -246,6 +255,7 @@ ...@@ -246,6 +255,7 @@
<if test="createUserCode != null">create_user_code = #{createUserCode},</if> <if test="createUserCode != null">create_user_code = #{createUserCode},</if>
<if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUserCode != null">update_user_code = #{updateUserCode},</if> <if test="updateUserCode != null">update_user_code = #{updateUserCode},</if>
<if test="inboundOrderId != null">inbound_order_id = #{inboundOrderId},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>
...@@ -286,6 +296,7 @@ ...@@ -286,6 +296,7 @@
<result property="createUserCode" column="create_user_code" /> <result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" /> <result property="updateUserCode" column="update_user_code" />
<result property="inboundOrderId" column="inbound_order_id" />
<result property="materialName" column="material_name" /> <result property="materialName" column="material_name" />
</resultMap> </resultMap>
</mapper> </mapper>
\ No newline at end of file
...@@ -94,9 +94,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -94,9 +94,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="selectInboundOrderItemsList" resultMap="InboundOrderItemsResult"> <select id="selectInboundOrderItemsList" resultMap="InboundOrderItemsResult">
select id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code select id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code, inbound_order_id
from inbound_order_items from inbound_order_items
where order_id = #{order_id} where inbound_order_id = #{inboundOrderId}
</select>
<select id="selectInboundOrdersByOrderId" resultType="InboundOrders">
select id, order_id
from inbound_orders
where order_id = #{orderId}
</select> </select>
<insert id="insertInboundOrders" parameterType="InboundOrders"> <insert id="insertInboundOrders" parameterType="InboundOrders">
...@@ -199,9 +205,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -199,9 +205,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete> </delete>
<insert id="batchInboundOrderItems"> <insert id="batchInboundOrderItems">
insert into inbound_order_items( id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code) values insert into inbound_order_items( id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code, inbound_order_id) values
<foreach item="item" index="index" collection="list" separator=","> <foreach item="item" index="index" collection="list" separator=",">
( #{item.id}, #{item.orderId}, #{item.materialId}, #{item.batchId}, #{item.warehouseId}, #{item.locationId}, #{item.plannedQuantity}, #{item.actualQuantity}, #{item.plannedPackages}, #{item.actualPackages}, #{item.divisor}, #{item.labelColor}, #{item.voucherNumber}, #{item.unitPrice}, #{item.itemStatus}, #{item.receivedAt}, #{item.receivedBy}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode}) ( #{item.id}, #{item.orderId}, #{item.materialId}, #{item.batchId}, #{item.warehouseId}, #{item.locationId}, #{item.plannedQuantity}, #{item.actualQuantity}, #{item.plannedPackages}, #{item.actualPackages}, #{item.divisor}, #{item.labelColor}, #{item.voucherNumber}, #{item.unitPrice}, #{item.itemStatus}, #{item.receivedAt}, #{item.receivedBy}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode}, #{item.inboundOrderId})
</foreach> </foreach>
</insert> </insert>
</mapper> </mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论