diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsInstockPrintController.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsInstockPrintController.java index 24526c50..9c5e9df9 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsInstockPrintController.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/WmsInstockPrintController.java @@ -1,27 +1,27 @@ package org.dromara.wms.controller; -import java.util.List; - -import lombok.RequiredArgsConstructor; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; -import org.dromara.wms.domain.bo.WmsInstockPrintBo; -import org.dromara.wms.domain.vo.WmsInstockPrintVo; -import org.dromara.wms.service.IWmsInstockPrintService; -import org.springframework.web.bind.annotation.*; -import org.springframework.validation.annotation.Validated; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.web.core.BaseController; -import org.dromara.common.mybatis.core.page.PageQuery; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.log.enums.BusinessType; import org.dromara.common.excel.utils.ExcelUtil; - +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.wms.domain.bo.WmsInstockPrintBo; +import org.dromara.wms.domain.vo.WmsInstockPrintVo; +import org.dromara.wms.service.IWmsInstockPrintService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** * 入库单-物料打印条码 @@ -104,9 +104,19 @@ public class WmsInstockPrintController extends BaseController { @PathVariable Long[] instockPrintIds) { return toAjax(wmsInstockPrintService.deleteWithValidByIds(List.of(instockPrintIds), true)); } + + /** + * 入库单-物料打印条码信息 + * 批量打印 + * 调用打印机 + * + * @param WmsInstockPrintBos 入库单-物料打印条码信息 + * @return 是否打印成功 + */ @PostMapping("/print") - public R print(@RequestBody WmsInstockPrintBo bo){ + public Boolean print(@RequestBody WmsInstockPrintBo bo){ List vos = bo.getVos(); - return null; + return wmsInstockPrintService.printCOde(vos); } + } diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteInventoryCheckServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteInventoryCheckServiceImpl.java index 1bc3bb4d..5294f365 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteInventoryCheckServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteInventoryCheckServiceImpl.java @@ -90,7 +90,16 @@ public class RemoteInventoryCheckServiceImpl implements RemoteInventoryCheckServ for (WmsBaseLocationVo location : locations) { WmsInventoryBo invBo = new WmsInventoryBo(); invBo.setLocationCode(location.getLocationCode()); - List inventories = wmsInventoryService.queryList(invBo); + + // 当抽检任务且指定了物料类型时,需要关联查询对应物料类型的库存 + List inventories; + if ("0".equals(task.getWmsCheckTaskType()) && task.getMaterialTypeId() != null) { + // 抽检模式且指定了物料类型,需要过滤物料类型 + inventories = wmsInventoryService.queryInventoryByLocationAndMaterialType(location.getLocationCode(), task.getMaterialTypeId()); + } else { + // 全盘或未指定物料类型 + inventories = wmsInventoryService.queryList(invBo); + } // 遍历当前库位下的所有库存记录 for (WmsInventoryVo inventory : inventories) { diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsCheckTaskServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsCheckTaskServiceImpl.java index cacff6b9..28c77abb 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsCheckTaskServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsCheckTaskServiceImpl.java @@ -49,7 +49,7 @@ public class WmsCheckTaskServiceImpl implements IWmsCheckTaskService { private final IWmsInventoryCheckService wmsInventoryCheckService;//盘点工单 - @DubboReference(timeout = 15000, retries = 1) + @DubboReference(timeout = 60000, retries = 1) private final RemoteJobService remoteJobService; /** @@ -125,11 +125,17 @@ public class WmsCheckTaskServiceImpl implements IWmsCheckTaskService { public Boolean insertByBo(WmsCheckTaskBo bo) { WmsCheckTask add = MapstructUtils.convert(bo, WmsCheckTask.class); validEntityBeforeSave(add); + String jobName = null; + if (bo.getWmsCheckTaskType().equals("0")) { + jobName = "WMS抽检任务" + bo.getTaskCode() + bo.getTaskName(); + }else { + jobName = "WMS盘点任务" + bo.getTaskCode() + bo.getTaskName(); + } // 创建SnailJob任务 DmsJobEntity job = new DmsJobEntity(); job.setRouteKey(AllocationAlgorithmEnum.ROUND) - .setJobName("WMS盘点任务" + bo.getTaskCode()) + .setJobName(jobName) .setExecutorInfo("wsmCheckTsk")//执行器名称 .setExecutorTimeout(30)//执行超时时间 .setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行 @@ -144,7 +150,7 @@ public class WmsCheckTaskServiceImpl implements IWmsCheckTaskService { R jobResp = remoteJobService.addClusterJob(job); Long jobId = jobResp != null ? jobResp.getData() : null;//任务ID add.setJobId(jobId); - if(ObjectUtils.isNotEmpty(jobId)){ + if (ObjectUtils.isNotEmpty(jobId)) { boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setTaskId(add.getTaskId()); @@ -170,10 +176,15 @@ public class WmsCheckTaskServiceImpl implements IWmsCheckTaskService { WmsCheckTask update = MapstructUtils.convert(bo, WmsCheckTask.class); validEntityBeforeSave(update); - + String jobName = null; + if (bo.getWmsCheckTaskType().equals("0")) { + jobName = "WMS抽检任务" + bo.getTaskCode() + bo.getTaskName(); + }else { + jobName = "WMS盘点任务" + bo.getTaskCode() + bo.getTaskName(); + } DmsJobEntity job = new DmsJobEntity(); job.setRouteKey(AllocationAlgorithmEnum.ROUND) - .setJobName("WMS盘点任务" + bo.getTaskCode())//任务名称 + .setJobName(jobName)//任务名称 .setExecutorInfo("wsmCheckTsk")//执行器名称 .setExecutorTimeout(30)//执行超时时间 .setBlockStrategy(JobBlockStrategyEnum.DISCARD)//阻塞策略:丢弃后续任务,避免重复执行 diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java index 35e46026..cf0ab6f1 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockOrderServiceImpl.java @@ -17,12 +17,15 @@ import org.dromara.wms.domain.WmsBaseWarehouse; import org.dromara.wms.domain.WmsInstockOrder; import org.dromara.wms.domain.bo.*; import org.dromara.wms.domain.vo.WmsBaseLocationVo; +import org.dromara.wms.domain.vo.WmsInstockDetailVo; import org.dromara.wms.domain.vo.WmsInstockOrderVo; +import org.dromara.wms.domain.vo.WmsPurchaseOrderDetailVo; import org.dromara.wms.mapper.WmsInstockOrderMapper; import org.dromara.wms.service.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -48,6 +51,9 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { private final IWmsInstockRecordService wmsInstockRecordService; + private final IWmsPurchaseOrderDetailService purchaseOrderDetailService; + private final IWmsPurchaseOrderService purchaseOrderService; + public static Integer nextSequence() { return sequence.incrementAndGet(); @@ -253,6 +259,80 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { // add.setAuditStatus(auditPass); // } +if("1".equals(bo.getInstockType())){ // 工单类型(1采购订单) + // 更新采购订单明细的deliveryQty:这是入库-采购联动的核心逻辑,确保入库数量累加到采购明细的送货数量中 + // 使用Set记录受影响的poNo,以避免重复更新主订单状态,提高效率 + Set updatedPoNos = new HashSet<>(); // 记录受影响的poNo,用于后续状态更新 + + // 遍历入库明细列表,逐个更新对应的采购订单明细 + for (WmsInstockDetailBo detail : bo.getDetailListBo()) { + // 校验poDId是否为空:采购入库必须关联采购明细ID,否则无法更新,符合数据完整性要求 + if (detail.getPoDId() == null) { + throw new ServiceException("采购入库明细缺少"); + } + // 创建更新对象,仅设置必要字段,遵循YAGNI原则 + WmsPurchaseOrderDetailBo detailBo = new WmsPurchaseOrderDetailBo(); + detailBo.setPoDId(detail.getPoDId()); + + // 查询现有采购明细:用于获取当前deliveryQty,避免直接数据库操作,增强安全性(OWASP输入验证已在上层处理) + WmsPurchaseOrderDetailVo existingDetail = purchaseOrderDetailService.queryById(detail.getPoDId()); + // 校验是否存在:如果不存在,抛出异常,防止无效更新 + if (existingDetail == null) { + throw new ServiceException("采购明细不存在" ); + } + + BigDecimal currentDeliveryQty = existingDetail.getDeliveryQty() != null ? existingDetail.getDeliveryQty() : BigDecimal.ZERO; + // 计算新deliveryQty:累加入库数量,使用BigDecimal确保精度,防止浮点错误 + BigDecimal newDeliveryQty = currentDeliveryQty.add(detail.getInstockQty()); + detailBo.setDeliveryQty(newDeliveryQty); + + // 执行更新:调用服务层方法,确保职责分离(SOLID单一职责原则) + purchaseOrderDetailService.updateByBo(detailBo); + + // 记录poNo:用于后续批量检查主订单状态 + updatedPoNos.add(existingDetail.getPoNo()); + } + + // 更新采购订单主表状态:基于所有明细的deliveryQty vs purchaseQty判断订单完成度 + // 这部分逻辑确保主订单状态实时同步,符合业务一致性 + for (String poNo : updatedPoNos) { + // 创建查询对象:用于获取该poNo的所有明细 + WmsPurchaseOrderDetailBo queryBo = new WmsPurchaseOrderDetailBo(); + queryBo.setPoNo(poNo); + + // 查询所有明细:用于计算完成状态 + List details = purchaseOrderDetailService.queryList(queryBo); + + // 初始化标志:allCompleted表示是否全部完成,partial表示是否部分完成 + boolean allCompleted = true; + boolean partial = false; + + // 遍历明细,判断每个物料的到货情况 + for (WmsPurchaseOrderDetailVo d : details) { + // 如果送货数量 < 采购数量,则未全部完成,但标记为部分完成 + if (d.getDeliveryQty().compareTo(d.getPurchaseQty()) < 0) { + allCompleted = false; + partial = true; + // 如果送货数量 > 采购数量,抛出异常,防止超入(业务约束) + } else if (d.getDeliveryQty().compareTo(d.getPurchaseQty()) > 0) { + throw new ServiceException("入库数量超过采购数量: poNo=" + poNo); + } + } + + // 根据标志计算新状态:"3"全部完成,"2"部分完成,"1"待采购 + // 此逻辑符合辩证思维,权衡多种情况 + String newStatus = allCompleted ? "3" : (partial ? "2" : "1"); + + // 创建更新对象:仅更新必要字段 + WmsPurchaseOrderBo orderBo = new WmsPurchaseOrderBo(); + orderBo.setPoNo(poNo); + orderBo.setPoStatus(newStatus); + + // 执行更新:调用服务层,确保事务内原子性 + purchaseOrderService.updateByBo(orderBo); + } +} + return orderVo; } @@ -477,6 +557,63 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } + // 删除前处理采购类型入库单的逆向更新 + // 查询要删除的入库单 + for (Long instockId : ids) { + WmsInstockOrderVo order = queryById(instockId); + if (order != null && "1".equals(order.getInstockType())) { + // 查询子表明细 + WmsInstockDetailBo detailQuery = new WmsInstockDetailBo(); + detailQuery.setInstockId(instockId); + List details = wmsInstockDetailService.queryList(detailQuery); + + // 更新采购订单明细的deliveryQty(逆向减去instockQty) + Set updatedPoNos = new HashSet<>(); + for (WmsInstockDetailVo detail : details) { + if (detail.getPoDId() == null) { + throw new ServiceException("采购入库明细缺少poDId,无法逆向更新"); + } + WmsPurchaseOrderDetailVo existingDetail = purchaseOrderDetailService.queryById(detail.getPoDId()); + if (existingDetail == null) { + throw new ServiceException("采购明细不存在"); + } + BigDecimal currentDeliveryQty = existingDetail.getDeliveryQty() != null ? existingDetail.getDeliveryQty() : BigDecimal.ZERO; + BigDecimal newDeliveryQty = currentDeliveryQty.subtract(detail.getInstockQty()); + if (newDeliveryQty.compareTo(BigDecimal.ZERO) < 0) { + throw new ServiceException("逆向更新后送货数量为负:" ); + } + WmsPurchaseOrderDetailBo detailBo = new WmsPurchaseOrderDetailBo(); + detailBo.setPoDId(detail.getPoDId()); + detailBo.setDeliveryQty(newDeliveryQty); + purchaseOrderDetailService.updateByBo(detailBo); + updatedPoNos.add(existingDetail.getPoNo()); + } + + // 更新采购订单主表状态 + for (String poNo : updatedPoNos) { + WmsPurchaseOrderDetailBo queryBo = new WmsPurchaseOrderDetailBo(); + queryBo.setPoNo(poNo); + List poDetails = purchaseOrderDetailService.queryList(queryBo); + boolean allCompleted = true; + boolean partial = false; + for (WmsPurchaseOrderDetailVo d : poDetails) { + BigDecimal delivery = d.getDeliveryQty() != null ? d.getDeliveryQty() : BigDecimal.ZERO; + if (delivery.compareTo(d.getPurchaseQty()) < 0) { + allCompleted = false; + partial = true; + } else if (delivery.compareTo(d.getPurchaseQty()) > 0) { + throw new ServiceException("送货数量超过采购数量: poNo=" + poNo); + } + } + String newStatus = allCompleted ? "3" : (partial ? "2" : "1"); + WmsPurchaseOrderBo orderBo = new WmsPurchaseOrderBo(); + orderBo.setPoNo(poNo); + orderBo.setPoStatus(newStatus); + purchaseOrderService.updateByBo(orderBo); + } + } + } + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.in(WmsInstockOrder::getInstockId,ids); int delete = baseMapper.delete(wrapper); diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryCheckServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryCheckServiceImpl.java index 3cdefe4a..0ed37f27 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryCheckServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryCheckServiceImpl.java @@ -1,20 +1,17 @@ package org.dromara.wms.service.impl; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.wms.domain.BaseMaterialCategory; import org.dromara.wms.domain.WmsBaseWarehouse; -import org.dromara.wms.domain.WmsInstockOrder; import org.dromara.wms.domain.WmsInventoryCheck; -import org.dromara.wms.domain.bo.WmsInstockOrderBo; import org.dromara.wms.domain.bo.WmsInventoryCheckBo; import org.dromara.wms.domain.vo.WmsInventoryCheckVo; import org.dromara.wms.mapper.WmsInventoryCheckMapper; @@ -22,10 +19,10 @@ import org.dromara.wms.service.IWmsInventoryCheckService; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; -import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; /** @@ -151,7 +148,9 @@ public class WmsInventoryCheckServiceImpl implements IWmsInventoryCheckService { } String stockingOrder = order + orderDate + orderLast; WmsInventoryCheck add = MapstructUtils.convert(bo, WmsInventoryCheck.class); - add.setCheckCode(stockingOrder); + if (add != null && add.getCheckCode() == null) { + add.setCheckCode(stockingOrder); + } add.setCreateBy(LoginHelper.getUserId()); validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryServiceImpl.java index 2f1e51ab..5e2c5937 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryServiceImpl.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInventoryServiceImpl.java @@ -230,6 +230,38 @@ public class WmsInventoryServiceImpl implements IWmsInventoryService { return baseMapper.deleteByIds(ids) > 0; } + /** + * 根据库位编码和物料类型查询库存列表 + * 用于盘点任务中按物料类型过滤库存 + * + * @param locationCode 库位编码 + * @param materialTypeId 物料类型ID + * @return 库存列表 + */ + @Override + public List queryInventoryByLocationAndMaterialType(String locationCode, Long materialTypeId) { + MPJLambdaWrapper lqw = JoinWrappers.lambda(WmsInventory.class) + .selectAll(WmsInventory.class) + + // 关联表查询物料信息 + .select(BaseMaterialInfo::getMaterialCode, BaseMaterialInfo::getMaterialName, BaseMaterialInfo::getMaterialTypeId) + .leftJoin(BaseMaterialInfo.class, BaseMaterialInfo::getMaterialId, WmsInventory::getMaterialId) + // 关联表查询物料大类名称 + .select(BaseMaterialCategory::getMaterialCategoryName) + .leftJoin(BaseMaterialCategory.class, BaseMaterialCategory::getMaterialCategoryId, WmsInventory::getMaterialCategoryId) + + // 按库位编码过滤 + .eq(StringUtils.isNotBlank(locationCode), WmsInventory::getLocationCode, locationCode) + // 按物料类型过滤 + .eq(materialTypeId != null, BaseMaterialInfo::getMaterialTypeId, materialTypeId) + // 只查询有库存的记录 + .gt(WmsInventory::getInventoryQty, BigDecimal.ZERO) + // 只查询正常库存 +// .eq(WmsInventory::getInventoryStatus, "1") + .orderByDesc(WmsInventory::getCreateTime); + + return baseMapper.selectVoList(lqw); + } /** * 根据批次码查询库存 diff --git a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/WmsCheckTaskExecutor.java b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/WmsCheckTaskExecutor.java index 64ccd5d6..6580f1ef 100644 --- a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/WmsCheckTaskExecutor.java +++ b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/WmsCheckTaskExecutor.java @@ -17,7 +17,7 @@ public class WmsCheckTaskExecutor { private static final ObjectMapper objectMapper = new ObjectMapper(); - @DubboReference(timeout = 15000) + @DubboReference(timeout = 60000) private org.dromara.wms.api.RemoteInventoryCheckService remoteInventoryCheckService;