From 5cae9b8fa7dc8a9aa7d48c8e4425f6d80786b7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Thu, 22 Jan 2026 12:38:50 +0800 Subject: [PATCH] =?UTF-8?q?WMS=E5=85=A5=E5=BA=93=E5=8D=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NoticeOrderApplicationService.java | 3 + .../ShiftManageApplicationService.java | 3 + .../StockInOrderApplicationService.java | 172 ++++++++++++++++++ .../StockOutOrderApplicationService.java | 3 + .../StockReceiptOrderApplicationService.java | 3 + .../dto/stockInOrder/StockInOrderDTO.java | 1 + .../stockInOrder/StockInOrderApi.java | 13 ++ .../stockInOrder/StockInOrderMapper.xml | 70 +++++++ 8 files changed, 268 insertions(+) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/noticeOrder/NoticeOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/noticeOrder/NoticeOrderApplicationService.java index 2096ab5da..91e5fa355 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/noticeOrder/NoticeOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/noticeOrder/NoticeOrderApplicationService.java @@ -139,6 +139,9 @@ public class NoticeOrderApplicationService { * @param noticeOrderDO */ private void setWarehouseInfo(NoticeOrderDO noticeOrderDO) { + if (noticeOrderDO.getWarehouseId() == null) { + throw new ServiceException("仓库ID不能为空"); + } AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(noticeOrderDO.getWarehouseId()); if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ throw new ServiceException("获取仓库信息失败"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java index 6c573a755..3aecb70bf 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java @@ -339,6 +339,9 @@ public class ShiftManageApplicationService { * @param shiftManageDO */ private void setWarehouseInfo(ShiftManageDO shiftManageDO) { + if (shiftManageDO.getWarehouseId() == null) { + throw new ServiceException("仓库ID不能为空"); + } AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(shiftManageDO.getWarehouseId()); if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ throw new ServiceException("获取仓库信息失败"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java index 4db45edd8..536ccf520 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java @@ -17,14 +17,26 @@ import com.mhd.system.api.domain.WarehouseFeignPO; import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO; import com.mhd.system.api.domain.cache.SystemServiceCacheUtil; import com.mhd.system.api.model.LoginUser; +import com.mhd.common.core.utils.poi.ExcelUtil; import com.mhd.wms.domain.stockInOrder.repository.po.StockInOrderPO; import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderDO; +import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.stockInOrder.service.StockInOrderDomainService; +import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; +import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO; +import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO; +import com.mhd.wms.interfaces.dto.stockInOrder.StockInOrderImportRowDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 入库单ApplicationService @@ -41,6 +53,8 @@ public class StockInOrderApplicationService { private UserServiceFeign userServiceFeign; @Autowired private SystemServiceFeign systemServiceFeign; + @Autowired + private IMaterialBaseInfoService materialBaseInfoService; /** @@ -106,6 +120,161 @@ public class StockInOrderApplicationService { return stockInOrderDomainService.getInfo(inOrderId); } + /** + * 导入入库单(Excel:一行=一个物料明细;以【委托编号NO】分组为一张入库单) + */ + public Boolean importData(MultipartFile file) { + if (file == null || file.isEmpty()) { + throw new ServiceException("导入文件不能为空"); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null) { + throw new ServiceException("登录已失效,请重新登录"); + } + + try (InputStream is = file.getInputStream()) { + ExcelUtil util = new ExcelUtil<>(StockInOrderImportRowDTO.class); + List rows = util.importExcel(is, 1); + if (rows == null || rows.isEmpty()) { + throw new ServiceException("导入数据为空"); + } + + // 过滤掉关键字段都为空的空行 + List validRows = rows.stream() + .filter(r -> ObjectUtil.isNotNull(r.getMaterialBaseInfoId()) || ObjectUtil.isNotNull(r.getShipperId()) || StringUtils.isNotBlank(r.getConsignmentNo())) + .collect(Collectors.toList()); + if (validRows.isEmpty()) { + throw new ServiceException("导入数据为空(可能全为空行)"); + } + + // 以委托编号NO分组;若为空则归到同一组(不推荐) + Map> groupMap = validRows.stream() + .collect(Collectors.groupingBy(r -> StringUtils.isBlank(r.getConsignmentNo()) ? "__EMPTY_CONSIGNMENT__" : r.getConsignmentNo())); + + List orderList = new ArrayList<>(); + for (Map.Entry> entry : groupMap.entrySet()) { + List groupRows = entry.getValue(); + StockInOrderImportRowDTO h = groupRows.get(0); + + if (ObjectUtil.isNull(h.getWarehouseId())) { + // 兜底:使用登录人当前关联仓库 + AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid()); + if (associationWarehouseCacheDO == null || associationWarehouseCacheDO.getWarehouseId() == null) { + throw new ServiceException("导入失败:仓库ID为空,且未配置用户关联仓库"); + } + h.setWarehouseId(associationWarehouseCacheDO.getWarehouseId()); + } + if (ObjectUtil.isNull(h.getShipperId())) { + throw new ServiceException("导入失败:货主ID不能为空(委托编号NO=" + h.getConsignmentNo() + ")"); + } + if (StringUtils.isBlank(h.getOrderTypeCode())) { + throw new ServiceException("导入失败:入库单据类型不能为空(委托编号NO=" + h.getConsignmentNo() + ")"); + } + + StockInOrderDO order = new StockInOrderDO(); + // 组织/审计字段 + order.setOrganizationId(loginUser.getUserPo().getOrganizationId()); + order.setOrganizationName(loginUser.getUserPo().getOrganizationName()); + order.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); + order.setCreateBy(loginUser.getUserid()); + order.setCreateByName(loginUser.getUsername()); + + // 必填/基础字段 + order.setWarehouseId(h.getWarehouseId()); + order.setShipperId(h.getShipperId()); + order.setSupplierId(h.getSupplierId()); + order.setOrderTypeCode(h.getOrderTypeCode()); + order.setConsignmentNo(h.getConsignmentNo()); + order.setRemark(h.getRemark()); + + // 报关表头字段 + order.setTo(h.getTo()); + order.setContactPerson(h.getContactPerson()); + order.setVehicleInfo(h.getVehicleInfo()); + order.setTel(h.getTel()); + order.setDriverSignature(h.getDriverSignature()); + order.setFax(h.getFax()); + order.setDeclarationArea(h.getDeclarationArea()); + order.setManufacturer(h.getManufacturer()); + order.setCustomsBrokerInfo(h.getCustomsBrokerInfo()); + order.setDeliveryAddress(h.getDeliveryAddress()); + order.setEntryExitCustoms(h.getEntryExitCustoms()); + order.setOriginDestinationCountry(h.getOriginDestinationCountry()); + order.setCarrier(h.getCarrier()); + order.setContainerNo(h.getContainerNo()); + order.setTransportMethod(h.getTransportMethod()); + order.setSupervisionMethod(h.getSupervisionMethod()); + order.setCustomsInspection(h.getCustomsInspection()); + order.setNeedCustomsDeclaration(h.getNeedCustomsDeclaration()); + order.setNeedTransport(h.getNeedTransport()); + // 日期字段:此处暂不做字符串转Date,避免格式不一致导致导入失败(如需强校验可再扩展) + + // 明细 + List details = new ArrayList<>(); + for (StockInOrderImportRowDTO r : groupRows) { + // 如果物料基础信息ID为空,尝试根据商品名称查询 + Long materialBaseInfoId = r.getMaterialBaseInfoId(); + if (ObjectUtil.isNull(materialBaseInfoId) && StringUtils.isNotBlank(r.getMaterialName())) { + MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO(); + materialBaseInfoDO.setMaterialName(r.getMaterialName()); + materialBaseInfoDO.setShipperId(h.getShipperId()); + List materialList = materialBaseInfoService.queryList(materialBaseInfoDO); + if (materialList == null || materialList.isEmpty()) { + throw new ServiceException("导入失败:根据商品名称【" + r.getMaterialName() + "】未找到物料基础信息(委托编号NO=" + h.getConsignmentNo() + ")"); + } + if (materialList.size() > 1) { + throw new ServiceException("导入失败:商品名称【" + r.getMaterialName() + "】匹配到多条物料基础信息,请使用物料基础信息ID(委托编号NO=" + h.getConsignmentNo() + ")"); + } + materialBaseInfoId = materialList.get(0).getMaterialBaseInfoId(); + } + if (ObjectUtil.isNull(materialBaseInfoId)) { + throw new ServiceException("导入失败:物料基础信息ID不能为空,且商品名称未匹配到物料(委托编号NO=" + h.getConsignmentNo() + ")"); + } + // 优先使用仓库数量,如果为空则使用计划数量 + BigDecimal quantity = r.getWarehouseQuantity() != null ? r.getWarehouseQuantity() : r.getQuantity(); + if (quantity == null) { + throw new ServiceException("导入失败:计划数量或仓库数量不能为空(委托编号NO=" + h.getConsignmentNo() + ",物料基础信息ID=" + materialBaseInfoId + ")"); + } + InMaterialDetailDO d = new InMaterialDetailDO(); + d.setMaterialBaseInfoId(materialBaseInfoId); + d.setQuantity(quantity); + d.setSpecification(r.getSpecification()); + d.setSkuCode(r.getSkuCode()); + d.setInvoiceNo(r.getInvoiceNo()); + d.setDeclaredQuantity(r.getDeclaredQuantity()); + d.setDeclaredUnit(r.getDeclaredUnit()); + d.setLiter(r.getLiter()); + d.setBoxCount(r.getBoxCount()); + d.setPieceCount(r.getPieceCount()); + d.setDimensions(r.getDimensions()); + d.setOutboundQuantity(r.getOutboundQuantity()); + d.setUnit(r.getUnit()); + d.setTotalNetWeight(r.getTotalNetWeight()); + d.setTotalGrossWeight(r.getTotalGrossWeight()); + d.setTotalVolume(r.getTotalVolume()); + d.setTotalArea(r.getTotalArea()); + d.setBatchRefNo(r.getBatchRefNo()); + d.setSheetRefNo(r.getSheetRefNo()); + d.setCountryOfOrigin(r.getCountryOfOrigin()); + d.setBoxPalletNo(r.getBoxPalletNo()); + d.setTotalPrice(r.getTotalPrice()); + d.setCurrency(r.getCurrency()); + d.setRemark(r.getDetailRemark()); + details.add(d); + } + order.setMaterialDetailList(details); + orderList.add(order); + } + + return stockInOrderDomainService.batchInsert(orderList); + } catch (ServiceException e) { + throw e; + } catch (Exception e) { + log.error("导入入库单失败", e); + throw new ServiceException("导入入库单失败:" + e.getMessage()); + } + } + /** * @description 审核入库单 @@ -148,6 +317,9 @@ public class StockInOrderApplicationService { * @param stockInOrderDO */ private void setWarehouseInfo(StockInOrderDO stockInOrderDO) { + if (stockInOrderDO.getWarehouseId() == null) { + throw new ServiceException("仓库ID不能为空"); + } AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockInOrderDO.getWarehouseId()); if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ throw new ServiceException("获取仓库信息失败"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java index 28e3f82d8..ada24a9b9 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java @@ -384,6 +384,9 @@ public class StockOutOrderApplicationService { * @param stockOutOrderDO */ private void setWarehouseInfo(StockOutOrderDO stockOutOrderDO) { + if (stockOutOrderDO.getWarehouseId() == null) { + throw new ServiceException("仓库ID不能为空"); + } AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockOutOrderDO.getWarehouseId()); if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ throw new ServiceException("获取仓库信息失败"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java index 392287747..2d59ff1cb 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java @@ -645,6 +645,9 @@ public class StockReceiptOrderApplicationService { * @param stockReceiptOrderDO */ private void setWarehouseInfo(StockReceiptOrderDO stockReceiptOrderDO) { + if (stockReceiptOrderDO.getWarehouseId() == null) { + throw new ServiceException("仓库ID不能为空"); + } AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockReceiptOrderDO.getWarehouseId()); if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ throw new ServiceException("获取仓库信息失败"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInOrder/StockInOrderDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInOrder/StockInOrderDTO.java index 49ed364e8..28495b2bd 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInOrder/StockInOrderDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/stockInOrder/StockInOrderDTO.java @@ -271,6 +271,7 @@ public class StockInOrderDTO extends StockInOrderBaseDTO { @Excel(name = "申报地关区") private String declarationArea; + @ApiModelProperty("生产商") @Excel(name = "生产商") private String manufacturer; diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java index cc727bdf6..9608cb718 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java @@ -3,6 +3,8 @@ package com.mhd.wms.interfaces.facadeApi.stockInOrder; import com.mhd.common.core.web.controller.BaseController; import com.mhd.common.core.web.domain.AjaxResult; import com.mhd.common.core.web.page.TableDataInfo; +import com.mhd.common.core.exception.ServiceException; +import com.mhd.common.core.utils.StringUtils; import com.mhd.wms.application.service.stockInOrder.StockInOrderApplicationService; import com.mhd.wms.domain.stockInOrder.repository.po.StockInOrderPO; import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderDO; @@ -11,6 +13,7 @@ import com.mhd.wms.interfaces.dto.stockInOrder.StockInOrderDTO; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.List; @@ -80,6 +83,16 @@ public class StockInOrderApi extends BaseController { return AjaxResult.success(stockInOrderApplicationService.getInfo(inOrderId)); } + /** + * 导入入库单 + */ + @ApiOperation("导入入库单") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file) + { + return AjaxResult.success(stockInOrderApplicationService.importData(file)); + } + /** * 审核入库单 diff --git a/mhd_wms/src/main/resources/mapper/stockInOrder/StockInOrderMapper.xml b/mhd_wms/src/main/resources/mapper/stockInOrder/StockInOrderMapper.xml index 205bf6bc6..5b0ba0e5d 100644 --- a/mhd_wms/src/main/resources/mapper/stockInOrder/StockInOrderMapper.xml +++ b/mhd_wms/src/main/resources/mapper/stockInOrder/StockInOrderMapper.xml @@ -293,6 +293,76 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{item} + + + and a."TO" like concat('%', #{to}, '%') + + + and a.CONTACT_PERSON like concat('%', #{contactPerson}, '%') + + + and a.VEHICLE_INFO like concat('%', #{vehicleInfo}, '%') + + + and a.CONSIGNMENT_NO like concat('%', #{consignmentNo}, '%') + + + and a.TEL like concat('%', #{tel}, '%') + + + and a.DRIVER_SIGNATURE like concat('%', #{driverSignature}, '%') + + + and a.FAX like concat('%', #{fax}, '%') + + + and a.DECLARATION_AREA like concat('%', #{declarationArea}, '%') + + + and a.MANUFACTURER like concat('%', #{manufacturer}, '%') + + + and a.CUSTOMS_BROKER_INFO like concat('%', #{customsBrokerInfo}, '%') + + + and a.DELIVERY_ADDRESS like concat('%', #{deliveryAddress}, '%') + + + and a.ENTRY_EXIT_CUSTOMS like concat('%', #{entryExitCustoms}, '%') + + + and a.ORIGIN_DESTINATION_COUNTRY like concat('%', #{originDestinationCountry}, '%') + + + and a.CARRIER like concat('%', #{carrier}, '%') + + + and a.CONTAINER_NO = #{containerNo} + + + and a.TRANSPORT_METHOD = #{transportMethod} + + + and a.SUPERVISION_METHOD = #{supervisionMethod} + + + and a.CUSTOMS_INSPECTION = #{customsInspection} + + + and a.NEED_CUSTOMS_DECLARATION = #{needCustomsDeclaration} + + + and a.NEED_TRANSPORT = #{needTransport} + + + and a.WAREHOUSE_DATE = #{warehouseDate} + + + and a.COMPLETION_TIME = #{completionTime} + + + and a.ORDER_DATE = #{orderDate} + and a.del_flag = #{delFlag} and a.del_flag = 1