diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java index 1dbedb634..8f6e08d00 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java @@ -3,6 +3,7 @@ package com.mhd.wms.application.service.materialInventory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.nacos.common.utils.CollectionUtils; +import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.utils.bean.BeanUtils; import com.mhd.common.core.utils.StringUtils; import com.mhd.common.core.web.domain.AjaxResult; @@ -22,6 +23,11 @@ import com.mhd.wms.interfaces.dto.materialInventory.MaterialInventoryDTO; import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; +import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; +import com.mhd.wms.domain.outMaterialDetail.repository.mapper.OutMaterialDetailMapper; +import com.mhd.wms.domain.stockOutOrder.repository.facade.IStockOutOrderService; +import com.mhd.wms.domain.stockOutOrder.repository.po.StockOutOrderPO; +import com.mhd.wms.util.BatchNoTokenUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -49,6 +55,10 @@ public class MaterialInventoryApplicationService { private MaterialInventoryMapper materialInventoryMapper; @Autowired private IMaterialBarCodeService materialBarCodeService; + @Autowired + private IStockOutOrderService stockOutOrderService; + @Autowired + private OutMaterialDetailMapper outMaterialDetailMapper; /** @@ -122,18 +132,26 @@ public class MaterialInventoryApplicationService { */ public List queryListWithBatchAttributes(MaterialInventoryDO materialInventoryDO) { List list = queryList(materialInventoryDO); - + fillBatchAttributes(list); + return list; + } + + /** + * 批量回填批次属性(isDisplay=1):拉取批次配置并从库存表取值,避免N+1查询。 + * 原为 queryListWithBatchAttributes 内部逻辑,抽出供可分配库存查询复用。 + */ + private void fillBatchAttributes(List list) { if (CollectionUtils.isEmpty(list)) { - return list; + return; } - + // 性能优化:批量获取批次属性,避免N+1查询问题 // 1. 收集所有唯一的materialBaseInfoId Set materialBaseInfoIdSet = list.stream() .map(MaterialInventoryPO::getMaterialBaseInfoId) .filter(Objects::nonNull) .collect(Collectors.toSet()); - + // 2. 批量查询批次属性(使用Map缓存,避免重复查询相同的materialBaseInfoId) Map> batchDetailMap = new HashMap<>(); for (Long materialBaseInfoId : materialBaseInfoIdSet) { @@ -154,12 +172,88 @@ public class MaterialInventoryApplicationService { log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage()); } } - + // 3. 为每个物料库存设置更多属性(从库存表中获取值) setMaterialMoreDetailListFromInventory(list, batchDetailMap); - + } + + /** + * 出库单明细可分配库存查询(库存分配弹窗专用),双模式: + * 模式A(推荐):传 outOrderId + materialDetailId,匹配值全部后端从出库单/明细自取—— + * 1) 物料编码必匹配(优先 materialBaseInfoId 精确,兜底 material_code); + * 2) 明细有箱号/卡板 → 同时匹配(多值拆 token,OR 命中); + * 3) 明细有 Sheet Ref NO's → 同时匹配(同上); + * 4) 货主、仓库取出库单 —— 替代前端 customerName 换算货主(客户≠货主时会误过滤)。 + * 模式B(平铺参数):不传双 ID 时,按 materialBaseInfoId|materialCode + boxPalletNo + sheetRefNo + * (可选 batchRefNo、shipperId、warehouseId)查询,多值串后端自动拆 token;条件正确性由调用方负责。 + * 两种模式均:只返回匹配到的库存行且可分配数量>0;不分页;不套用 queryList 的用户组织数据权限。 + */ + public List queryAssignableList(Long outOrderId, Long materialDetailId, MaterialInventoryDTO flatQuery) { + MaterialInventoryDO query; + if (outOrderId != null || materialDetailId != null) { + if (outOrderId == null || materialDetailId == null) { + throw new ServiceException("outOrderId 与 materialDetailId 必须成对传入"); + } + query = buildAssignableQueryByOutOrder(outOrderId, materialDetailId); + } else { + query = buildAssignableQueryByFlatParams(flatQuery); + } + List list = materialInventoryMapper.queryAssignableList(query); + fillBatchAttributes(list); return list; } + + /** + * 模式A:按出库单+明细自取匹配条件 + */ + private MaterialInventoryDO buildAssignableQueryByOutOrder(Long outOrderId, Long materialDetailId) { + StockOutOrderPO order = stockOutOrderService.getInfo(outOrderId); + if (order == null) { + throw new ServiceException("出库单不存在"); + } + OutMaterialDetail detail = outMaterialDetailMapper.selectById(materialDetailId); + if (detail == null || !Integer.valueOf(1).equals(detail.getDelFlag())) { + throw new ServiceException("出库单物料明细不存在"); + } + if (detail.getMaterialBaseInfoId() == null + && StringUtils.isBlank(detail.getMaterialCode()) + && StringUtils.isBlank(detail.getMaterialNo())) { + throw new ServiceException("物料明细缺少物料信息,无法查询可分配库存"); + } + + MaterialInventoryDO query = new MaterialInventoryDO(); + query.setShipperId(order.getShipperId()); + query.setWarehouseId(detail.getWarehouseId() != null + ? detail.getWarehouseId() : order.getWarehouseId()); + query.setMaterialBaseInfoId(detail.getMaterialBaseInfoId()); + if (detail.getMaterialBaseInfoId() == null) { + query.setMaterialCode(StringUtils.isNotBlank(detail.getMaterialCode()) + ? detail.getMaterialCode() : detail.getMaterialNo()); + } + // 需求匹配键:物料 + 箱号/卡板 + Sheet Ref NO's;batchRefNoList 默认不赋值(不参与匹配) + query.setBoxPalletNoList(BatchNoTokenUtil.splitTokens(detail.getBoxPalletNo())); + query.setSheetRefNoList(BatchNoTokenUtil.splitTokens(detail.getSheetRefNo())); + return query; + } + + /** + * 模式B:平铺参数构造匹配条件(条件正确性由调用方负责;至少要有物料标识) + */ + private MaterialInventoryDO buildAssignableQueryByFlatParams(MaterialInventoryDTO flatQuery) { + if (flatQuery == null + || (flatQuery.getMaterialBaseInfoId() == null && StringUtils.isBlank(flatQuery.getMaterialCode()))) { + throw new ServiceException("请传 outOrderId+materialDetailId,或至少传 materialBaseInfoId / materialCode"); + } + MaterialInventoryDO query = new MaterialInventoryDO(); + query.setShipperId(flatQuery.getShipperId()); + query.setWarehouseId(flatQuery.getWarehouseId()); + query.setMaterialBaseInfoId(flatQuery.getMaterialBaseInfoId()); + query.setMaterialCode(flatQuery.getMaterialCode()); + query.setBoxPalletNoList(BatchNoTokenUtil.splitTokens(flatQuery.getBoxPalletNo())); + query.setSheetRefNoList(BatchNoTokenUtil.splitTokens(flatQuery.getSheetRefNo())); + query.setBatchRefNoList(BatchNoTokenUtil.splitTokens(flatQuery.getBatchRefNo())); + return query; + } /** * 为物料库存设置更多属性(从库存表中获取值) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/reviewOrder/ReviewOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/reviewOrder/ReviewOrderApplicationService.java index 3e6d14052..23427cd72 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/reviewOrder/ReviewOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/reviewOrder/ReviewOrderApplicationService.java @@ -182,9 +182,11 @@ public class ReviewOrderApplicationService { Map> batchDetailMap = loadDisplayBatchDetailMap(details); fillDynamicBatchDisplayFields(details, batchDetailMap); buildReviewMaterialMoreDetailListLikeShelf(details, batchDetailMap); + fillHeaderSummary(header, details); header.setMaterialDetailList(details); return header; } + public ReviewOrderPO getDetailByReviewOrderNumber(String reviewOrderNumber) { if (StringUtils.isEmpty(reviewOrderNumber)) { @@ -199,6 +201,7 @@ public class ReviewOrderApplicationService { Map> batchDetailMap = loadDisplayBatchDetailMap(details); fillDynamicBatchDisplayFields(details, batchDetailMap); buildReviewMaterialMoreDetailListLikeShelf(details, batchDetailMap); + fillHeaderSummary(header, details); header.setMaterialDetailList(details); return header; } @@ -854,6 +857,36 @@ public class ReviewOrderApplicationService { return v == null ? BigDecimal.ZERO : v; } + /** + * 详情头表回填合计。口径与列表 queryList 聚合(ReviewOrderMapper.xml)严格一致: + * totalPlanQty = Σ ifnull(material_plan_qty, ifnull(pending_review_qty,0) + ifnull(reviewed_qty,0)) + * totalReviewedQty = Σ ifnull(reviewed_qty,0) —— 即「出库总数量(取已复核数量)」 + * materialKindCount = count(distinct material_base_info_id) + */ + private void fillHeaderSummary(ReviewOrderPO header, List details) { + BigDecimal totalPlan = BigDecimal.ZERO; + BigDecimal totalReviewed = BigDecimal.ZERO; + Set materialIdSet = new HashSet<>(); + if (!CollectionUtils.isEmpty(details)) { + for (ReviewMaterialDetailPO d : details) { + if (d == null) { + continue; + } + BigDecimal plan = d.getMaterialPlanQty() != null + ? d.getMaterialPlanQty() + : nz(d.getPendingReviewQty()).add(nz(d.getReviewedQty())); + totalPlan = totalPlan.add(plan); + totalReviewed = totalReviewed.add(nz(d.getReviewedQty())); + if (d.getMaterialBaseInfoId() != null) { + materialIdSet.add(d.getMaterialBaseInfoId()); + } + } + } + header.setTotalPlanQty(totalPlan); + header.setTotalReviewedQty(totalReviewed); + header.setMaterialKindCount(materialIdSet.size()); + } + /** * 详情展示口径: * reviewQtyEa 展示待复核数量,cancelQty 展示已复核数量。 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 8762d34b0..50c3e19cd 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 @@ -37,7 +37,10 @@ import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO; import com.mhd.wms.domain.materialInventory.entity.MaterialInventory; import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper; import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO; +import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO; import com.mhd.wms.domain.materialInventory.service.MaterialInventoryDomainService; +import com.mhd.wms.util.BatchNoTokenUtil; +import com.mhd.wms.util.TongyuOrgUtil; import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.repository.facade.IOutMaterialDetailService; @@ -1005,24 +1008,46 @@ public class StockOutOrderApplicationService { .eq(OutMaterialDetail::getOutOrderNumber, stockOutOrderDb.getOutOrderNumber())); List materialDetailList = cn.hutool.core.bean.BeanUtil.copyToList(outMaterialDetailList, OutMaterialDetailDO.class); List materialDetailList2 = new ArrayList<>(); + // 仅通宇账号启用与库存分配弹窗同口径的新匹配(物料+箱号/卡板+Sheet Ref 多值拆 token); + // 其他账号保持原 eq 精确匹配行为不变 + boolean tongyuAssign = TongyuOrgUtil.isTongyu(SecurityUtils.getLoginUser()); for (OutMaterialDetailDO detail : materialDetailList) { String batchRefNo = detail.getBatchRefNo(); String sheetRefNo = detail.getSheetRefNo(); String boxPalletNo = detail.getBoxPalletNo(); Long materialBaseInfoId = detail.getMaterialBaseInfoId(); Long warehouseId = detail.getWarehouseId(); - List materialInventories = materialInventoryMapper.selectList(new QueryWrapper().lambda() - .eq(MaterialInventory::getBatchRefNo, batchRefNo) - .eq(MaterialInventory::getSheetRefNo, sheetRefNo) - .eq(MaterialInventory::getBoxPalletNo, boxPalletNo) - .eq(MaterialInventory::getWarehouseId, warehouseId) - .eq(MaterialInventory::getMaterialBaseInfoId, materialBaseInfoId)); + List materialInventories; + if (tongyuAssign) { + MaterialInventoryDO assignQuery = new MaterialInventoryDO(); + assignQuery.setShipperId(stockOutOrderDb.getShipperId()); + assignQuery.setWarehouseId(warehouseId != null ? warehouseId : stockOutOrderDb.getWarehouseId()); + assignQuery.setMaterialBaseInfoId(materialBaseInfoId); + assignQuery.setBoxPalletNoList(BatchNoTokenUtil.splitTokens(boxPalletNo)); + assignQuery.setSheetRefNoList(BatchNoTokenUtil.splitTokens(sheetRefNo)); + materialInventories = materialInventoryMapper.queryAssignableList(assignQuery); + } else { + List legacyInventories = materialInventoryMapper.selectList(new QueryWrapper().lambda() + .eq(MaterialInventory::getBatchRefNo, batchRefNo) + .eq(MaterialInventory::getSheetRefNo, sheetRefNo) + .eq(MaterialInventory::getBoxPalletNo, boxPalletNo) + .eq(MaterialInventory::getWarehouseId, warehouseId) + .eq(MaterialInventory::getMaterialBaseInfoId, materialBaseInfoId)); + materialInventories = new ArrayList<>(); + if (legacyInventories != null) { + for (MaterialInventory mi : legacyInventories) { + MaterialInventoryPO po = new MaterialInventoryPO(); + cn.hutool.core.bean.BeanUtil.copyProperties(mi, po); + materialInventories.add(po); + } + } + } if (materialInventories == null || materialInventories.isEmpty()) { throw new ServiceException("库存不存在:" + batchRefNo + " " + sheetRefNo + " " + boxPalletNo); } BigDecimal remainingQuantity = detail.getQuantity(); // 计划数量 - for (MaterialInventory materialInventory : materialInventories) { + for (MaterialInventoryPO materialInventory : materialInventories) { if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) { break; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java index 58fbf0e2f..4da220e1c 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/mapper/MaterialInventoryMapper.java @@ -41,6 +41,14 @@ public interface MaterialInventoryMapper extends BaseMapper //查物料库存列表-按货主+物料+仓库(库存查询第三个页签,update_time 取合并后最大值) public List queryListByHzWlUnit(MaterialInventoryDO materialInventoryDO); + /** + * 出库单明细可分配库存查询(库存分配弹窗专用): + * 物料必匹配(materialBaseInfoId 精确 / material_code 兜底); + * 箱号/卡板、Sheet Ref NO's(及可选 Batch Ref NO's)按 token 列表 OR-LIKE 同时匹配(明细多值拆分后传入); + * 货主/仓库由调用方取自出库单;仅返回 del_flag=1 且可分配数量(allocation_quantity)>0 的库存行。 + */ + public List queryAssignableList(MaterialInventoryDO materialInventoryDO); + /** * @description 批量增加库存 * @author ZhouGY diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryDO.java index fcff6786f..a5b752277 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryDO.java @@ -262,4 +262,13 @@ public class MaterialInventoryDO extends MaterialBaseDO { private String updateTimeStart; private String updateTimeEnd; + + @ApiModelProperty("库存分配匹配:箱号/卡板号 token 列表(明细多值拆分后,OR 匹配;空则不参与匹配)") + private List boxPalletNoList; + + @ApiModelProperty("库存分配匹配:Sheet Ref NO's token 列表(明细多值拆分后,OR 匹配;空则不参与匹配)") + private List sheetRefNoList; + + @ApiModelProperty("库存分配匹配:Batch Ref NO's token 列表(默认不启用,仅显式赋值时参与匹配)") + private List batchRefNoList; } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java index d40fdcc1a..2369c4637 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java @@ -8,6 +8,7 @@ import com.mhd.common.core.utils.StringUtils; 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.security.utils.SecurityUtils; import com.mhd.system.api.UserServiceFeign; import com.mhd.wms.application.service.materialInventory.MaterialInventoryApplicationService; import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO; @@ -17,6 +18,7 @@ import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryQue import com.mhd.wms.interfaces.assember.materialInventory.MaterialInventoryAssembler; import com.mhd.wms.interfaces.dto.materialInventory.MaterialInventoryDTO; import com.mhd.wms.interfaces.dto.materialInventory.MaterialInventoryQueryListDTO; +import com.mhd.wms.util.TongyuOrgUtil; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -138,6 +140,36 @@ public class MaterialInventoryApi extends BaseController { return tableDataInfo; } + /** + * 出库单明细可分配库存(库存分配弹窗专用)——按通宇账号分流: + * 通宇账号(组织ID=2830 或 组织名含「通宇」):启用需求三新逻辑,双模式入参—— + * 模式A(推荐):传 outOrderId + materialDetailId,物料/箱号/卡板/Sheet Ref/货主/仓库 全部后端自取; + * 模式B(平铺参数,与旧 /list 传参风格一致):不传双 ID 时,按 materialBaseInfoId|materialCode + * + boxPalletNo + sheetRefNo(可选 batchRefNo、shipperId、warehouseId)查询,多值串后端自动拆分。 + * 两种模式均:仅返回可分配数量>0 的匹配行;不分页。 + * 非通宇账号:保持原行为,内部按原 /list 逻辑查询(分页、customerName 换算等与库存查询页完全一致)。 + */ + @ApiOperation("出库单明细可分配库存列表(仅通宇账号启用新匹配逻辑,其他账号按原 /list 逻辑查询)") + @GetMapping("/assignableList") + public TableDataInfo assignableList(MaterialInventoryDTO materialInventoryDTO, + @RequestParam(value = "outOrderId", required = false) Long outOrderId, + @RequestParam(value = "materialDetailId", required = false) Long materialDetailId, + @RequestParam(value = "customerName", required = false) String customerName, + @RequestParam(value = "excludeZeroInventoryQuantity", required = false) Boolean excludeZeroInventoryQuantity, + @RequestParam(value = "expiryDateStart", required = false) String expiryDateStart, + @RequestParam(value = "expiryDateEnd", required = false) String expiryDateEnd, + @RequestParam(value = "orderByExpiryDate", required = false) Boolean orderByExpiryDate) { + // 仅通宇账号启用需求三新逻辑(物料+箱号/卡板+Sheet Ref 匹配、可分配>0、不分页);其他账号保持原 /list 行为 + if (TongyuOrgUtil.isTongyu(SecurityUtils.getLoginUser())) { + List list = materialInventoryApplicationService.queryAssignableList(outOrderId, materialDetailId, materialInventoryDTO); + return getDataTable(list); + } + // materialDetailId 是新接口专用参数(出库单明细ID),库存 DTO 的同名字段语义是「上架单明细ID」, + // 泄入原查询会生成错误的 a.material_detail_id 条件导致查空,进原查询前显式清除 + materialInventoryDTO.setMaterialDetailId(null); + return list(materialInventoryDTO, customerName, excludeZeroInventoryQuantity, expiryDateStart, expiryDateEnd, orderByExpiryDate); + } + @ApiOperation("查询物料库存列表不分页;queryRule=hz 时按货主+物料分组(同一物料在不同货主各占一行)") @GetMapping("/listAll") public TableDataInfo listAll(MaterialInventoryDTO materialInventoryDTO) diff --git a/mhd_wms/src/main/java/com/mhd/wms/util/BatchNoTokenUtil.java b/mhd_wms/src/main/java/com/mhd/wms/util/BatchNoTokenUtil.java new file mode 100644 index 000000000..99371619a --- /dev/null +++ b/mhd_wms/src/main/java/com/mhd/wms/util/BatchNoTokenUtil.java @@ -0,0 +1,40 @@ +package com.mhd.wms.util; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 出库分配批次属性多值拆分工具。 + * 出库明细的箱号/卡板号、Sheet Ref NO's、Batch Ref NO's 可能是「多个值拼接的字符串」 + * (如 Excel 导入单元格原样入库),而库存表每行通常只有一个(或多个拼接的)值; + * 直接整串 LIKE 匹配不到任何行,是「可分配库存不完整」的主要根因。 + * + * @author rcx + */ +public final class BatchNoTokenUtil { + + /** 英文/中文逗号、分号、顿号、斜杠、空白 */ + private static final String SEPARATOR_REGEX = "[,,;;、/\\s]+"; + + private BatchNoTokenUtil() { + } + + /** + * 按常见分隔符拆分;trim、去空、去重。 + * + * @param value 明细上的批次属性原始值 + * @return token 列表;无可拆内容时返回 null(表示「不参与匹配」) + */ + public static List splitTokens(String value) { + if (value == null || value.trim().isEmpty()) { + return null; + } + List tokens = Arrays.stream(value.split(SEPARATOR_REGEX)) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .collect(Collectors.toList()); + return tokens.isEmpty() ? null : tokens; + } +} diff --git a/mhd_wms/src/main/java/com/mhd/wms/util/TongyuOrgUtil.java b/mhd_wms/src/main/java/com/mhd/wms/util/TongyuOrgUtil.java new file mode 100644 index 000000000..3d5260c7e --- /dev/null +++ b/mhd_wms/src/main/java/com/mhd/wms/util/TongyuOrgUtil.java @@ -0,0 +1,44 @@ +package com.mhd.wms.util; + +import com.mhd.common.core.utils.StringUtils; +import com.mhd.system.api.model.LoginUser; + +/** + * 通宇组织/账号判断工具。 + * 口径来源:既有代码约定「通宇组织ID=2830」(见 HandoverTaskOrderDomainService/StockOutOrderApplicationService 注释)。 + * 由于测试/生产环境组织 ID 可能不一致(仓库 ID 已知存在差异),同时按组织名称兜底。 + * + * @author rcx + */ +public final class TongyuOrgUtil { + + /** 通宇组织ID(生产口径,见既有代码注释) */ + public static final Long TONGYU_ORGANIZATION_ID = 2830L; + + /** 组织名称关键字 */ + private static final String TONGYU_KEYWORD = "通宇"; + + private TongyuOrgUtil() { + } + + /** + * 当前登录账号是否属于通宇组织 + */ + public static boolean isTongyu(LoginUser loginUser) { + if (loginUser == null || loginUser.getUserPo() == null) { + return false; + } + if (TONGYU_ORGANIZATION_ID.equals(loginUser.getUserPo().getOrganizationId())) { + return true; + } + return StringUtils.isNotBlank(loginUser.getUserPo().getOrganizationName()) + && loginUser.getUserPo().getOrganizationName().contains(TONGYU_KEYWORD); + } + + /** + * 按组织ID判断是否通宇(单据维度兜底用) + */ + public static boolean isTongyuOrganizationId(Long organizationId) { + return TONGYU_ORGANIZATION_ID.equals(organizationId); + } +} diff --git a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml index 4af9498d9..cfeb130d3 100644 --- a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml +++ b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml @@ -396,6 +396,63 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" group by a.MATERIAL_INVENTORY_ID order by sort_order, a.update_time desc + + +