diff --git a/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/DeliverSubCategoryEnum.java b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/DeliverSubCategoryEnum.java new file mode 100644 index 00000000..e94a48dd --- /dev/null +++ b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/DeliverSubCategoryEnum.java @@ -0,0 +1,21 @@ +package com.chanko.yunxi.mes.module.heli.enums; + +import lombok.Getter; + +/** + * 项目订单状态枚举 + * @author chenxi + * @date 2024-01-18 01:19 + */ +@Getter +public enum DeliverSubCategoryEnum { + DELIVER_LIST("发货清单"), + OTHER_LIST("其他清单") + ; + + private String description; + + DeliverSubCategoryEnum(String description) { + this.description = description; + } +} diff --git a/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ErrorCodeConstants.java b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ErrorCodeConstants.java index 93254126..e01c3872 100644 --- a/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ErrorCodeConstants.java +++ b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ErrorCodeConstants.java @@ -49,8 +49,8 @@ public interface ErrorCodeConstants { /************订单管理***********/ ErrorCode PROJECT_ORDER_NOT_EXISTS = new ErrorCode(1_004_001, "项目订单不存在"); - /************发货管理***********/ ErrorCode DELIVER_ORDER_NOT_EXISTS = new ErrorCode(1_005_001, "发货订单不存在"); - + ErrorCode RELATION_PROJECT_ORDER_HAS_DONE = new ErrorCode(1_005_002, "关联项目订单已经发货完成"); + ErrorCode DELIVER_AMOUNT_OVERFLOW = new ErrorCode(1_005_003, "超额发货"); } diff --git a/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ProjectOrderDeliverStatusEnum.java b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ProjectOrderDeliverStatusEnum.java new file mode 100644 index 00000000..4609f4ff --- /dev/null +++ b/mes-module-heli/mes-module-heli-api/src/main/java/com/chanko/yunxi/mes/module/heli/enums/ProjectOrderDeliverStatusEnum.java @@ -0,0 +1,24 @@ +package com.chanko.yunxi.mes.module.heli.enums; + +import lombok.Getter; + +/** + * 项目订单状态枚举 + * @author chenxi + * @date 2024-01-18 01:19 + */ +@Getter +public enum ProjectOrderDeliverStatusEnum { + NOT(1, "未发货"), + PART(2, "部分发货"), + ALL(3, "全部发货") + ; + + private int code; + private String description; + + ProjectOrderDeliverStatusEnum(int code, String description) { + this.code = code; + this.description = description; + } +} diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/deliverorder/vo/DeliverOrderSaveReqVO.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/deliverorder/vo/DeliverOrderSaveReqVO.java index 6db72db3..e61dc76a 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/deliverorder/vo/DeliverOrderSaveReqVO.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/deliverorder/vo/DeliverOrderSaveReqVO.java @@ -1,13 +1,15 @@ package com.chanko.yunxi.mes.module.heli.controller.admin.deliverorder.vo; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverordersub.DeliverOrderSubDO; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import javax.validation.constraints.*; -import java.util.*; -import org.springframework.format.annotation.DateTimeFormat; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; -import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverordersub.DeliverOrderSubDO; +import java.util.List; @Schema(description = "管理后台 - 发货订单新增/修改 Request VO") @Data @@ -85,7 +87,11 @@ public class DeliverOrderSaveReqVO { @Schema(description = "操作意见") private String activeOpinion; + @Valid @Schema(description = "发货订单子项列表") private List deliverOrderSubs; + @Valid + @Schema(description = "发货订单子项列表") + private List deliverOrderOtherSubs; } diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/dataobject/deliverorder/DeliverOrderSubDO.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/dataobject/deliverorder/DeliverOrderSubDO.java index 61c31d03..05c6e7f0 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/dataobject/deliverorder/DeliverOrderSubDO.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/dataobject/deliverorder/DeliverOrderSubDO.java @@ -7,6 +7,8 @@ import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.*; import com.chanko.yunxi.mes.framework.mybatis.core.dataobject.BaseDO; +import javax.validation.constraints.Min; + /** * 发货订单子项 DO * @@ -48,6 +50,7 @@ public class DeliverOrderSubDO extends BaseDO { /** * 数量 */ + @Min(value = 1, message = "数量必须大于零") private Integer amount; /** * 单位 diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/mysql/projectorder/ProjectOrderMapper.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/mysql/projectorder/ProjectOrderMapper.java index d01d3d2d..647fc7ed 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/mysql/projectorder/ProjectOrderMapper.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/dal/mysql/projectorder/ProjectOrderMapper.java @@ -49,10 +49,11 @@ public interface ProjectOrderMapper extends BaseMapperX { default ProjectOrderDO selectById(Long id) { MPJLambdaWrapper query = new MPJLambdaWrapper<>(); query.selectAll(ProjectOrderDO.class) - .select("u.nickname as businessManName", "d.name as businessDeptName", "u1.nickname as creatorName") + .select("u.nickname as businessManName", "d.name as businessDeptName", "u1.nickname as creatorName", "e.name as customerName") .leftJoin(AdminUserDO.class, "u", AdminUserDO::getId, ProjectOrderDO::getBusinessMan) .leftJoin(AdminUserDO.class, "u1", AdminUserDO::getId, ProjectOrderDO::getCreator) .leftJoin(DeptDO.class, "d", DeptDO::getId, ProjectOrderDO::getBusinessDeptId) + .leftJoin(CustomerDO.class, "e", CustomerDO::getId, ProjectOrderDO::getCustomerId) .eq(ProjectOrderDO::getId, id) .last("LIMIT 1") .disableSubLogicDel(); diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/manager/CrossOrderStatusManager.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/manager/CrossOrderStatusManager.java new file mode 100644 index 00000000..4194a5f6 --- /dev/null +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/manager/CrossOrderStatusManager.java @@ -0,0 +1,81 @@ +package com.chanko.yunxi.mes.module.heli.manager; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverorder.DeliverOrderDO; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverordersub.DeliverOrderSubDO; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.projectorder.ProjectOrderDO; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.projectorder.ProjectOrderSubDO; +import com.chanko.yunxi.mes.module.heli.dal.mysql.deliverordersub.DeliverOrderSubMapper; +import com.chanko.yunxi.mes.module.heli.dal.mysql.projectorder.ProjectOrderMapper; +import com.chanko.yunxi.mes.module.heli.dal.mysql.projectorder.ProjectOrderSubMapper; +import com.chanko.yunxi.mes.module.heli.enums.DeliverOrderStatusEnum; +import com.chanko.yunxi.mes.module.heli.enums.ProjectOrderDeliverStatusEnum; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 跨订单状态交互管理器 + * + * @author chenxi + * @date 2024-01-31 10:03 + */ +@Component +public class CrossOrderStatusManager { + + @Resource + private ProjectOrderMapper projectOrderMapper; + @Resource + private ProjectOrderSubMapper projectOrderSubMapper; + @Resource + private DeliverOrderSubMapper deliverOrderSubMapper; + + /** + * 刷新项目订单发货状态 + * @param projectOrderIds + */ + @Transactional(rollbackFor = Exception.class) + public void refreshProjectOrderDeliverStatus(String... projectOrderIds) { + // 锁定订单 + for (String projectOrderId : projectOrderIds) { + ProjectOrderDO projectOrderDO = projectOrderMapper.selectOne(new LambdaQueryWrapper() {{ + eq(ProjectOrderDO::getId, projectOrderId); + last("LIMIT 1 FOR UPDATE"); + }}); + + // 查询关联子项 + List projectOrderSubDOList = projectOrderSubMapper.selectListByProjectOrderId(projectOrderDO.getId()); + + // 查询发货记录 + MPJLambdaWrapper historyDeliveredSubQuery = new MPJLambdaWrapper<>(); + historyDeliveredSubQuery.selectAll(DeliverOrderSubDO.class) + .leftJoin(DeliverOrderDO.class, DeliverOrderDO::getId, DeliverOrderSubDO::getDeliveryOrderId) + .eq(DeliverOrderDO::getDeliverStatus, DeliverOrderStatusEnum.DELIVER.getCode()) + .in(DeliverOrderSubDO::getSaleOrderSubId, projectOrderSubDOList.stream().map(ProjectOrderSubDO::getId).collect(Collectors.toSet())); + List historyDeliveredSubList = deliverOrderSubMapper.selectList(historyDeliveredSubQuery); + if(historyDeliveredSubList.isEmpty()) return; + Map> historyDeliveredSubsGroupBySaleSubId = historyDeliveredSubList.stream().collect(Collectors.groupingBy(DeliverOrderSubDO::getSaleOrderSubId)); + + // 考虑变更订单情况 只需判断历史发货是否大于等于订单子项数量 + boolean allDone = projectOrderSubDOList.stream().allMatch(projectOrderSubDO -> { + List historySubList = historyDeliveredSubsGroupBySaleSubId.get(projectOrderSubDO.getId()); + int historyDeliveredAmount = historySubList == null || historySubList.isEmpty() ? 0 : historySubList.stream().mapToInt(DeliverOrderSubDO::getAmount).sum(); + return historyDeliveredAmount >= projectOrderSubDO.getAmount(); + }); + + if(allDone){ + projectOrderDO.setDeliveryStatus(ProjectOrderDeliverStatusEnum.ALL.getCode()); + }else{ + projectOrderDO.setDeliveryStatus(ProjectOrderDeliverStatusEnum.PART.getCode()); + } + projectOrderMapper.updateById(projectOrderDO); + + } + + } +} diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/deliverorder/DeliverOrderServiceImpl.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/deliverorder/DeliverOrderServiceImpl.java index 12396359..6b3267b7 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/deliverorder/DeliverOrderServiceImpl.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/deliverorder/DeliverOrderServiceImpl.java @@ -8,25 +8,34 @@ import com.chanko.yunxi.mes.module.heli.controller.admin.deliverorder.vo.Deliver import com.chanko.yunxi.mes.module.heli.controller.admin.deliverorder.vo.DeliverOrderSaveReqVO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverorder.DeliverOrderDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverordersub.DeliverOrderSubDO; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.projectorder.ProjectOrderDO; +import com.chanko.yunxi.mes.module.heli.dal.dataobject.projectorder.ProjectOrderSubDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.serialnumber.SerialNumberDO; import com.chanko.yunxi.mes.module.heli.dal.mysql.deliverorder.DeliverOrderMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.deliverordersub.DeliverOrderSubMapper; +import com.chanko.yunxi.mes.module.heli.dal.mysql.projectorder.ProjectOrderMapper; +import com.chanko.yunxi.mes.module.heli.dal.mysql.projectorder.ProjectOrderSubMapper; import com.chanko.yunxi.mes.module.heli.enums.BusinesTypeEnum; import com.chanko.yunxi.mes.module.heli.enums.DeliverOrderStatusEnum; +import com.chanko.yunxi.mes.module.heli.enums.ProjectOrderDeliverStatusEnum; +import com.chanko.yunxi.mes.module.heli.manager.CrossOrderStatusManager; import com.chanko.yunxi.mes.module.heli.service.serialnumber.SerialNumberService; +import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import javax.validation.Valid; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static com.chanko.yunxi.mes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.chanko.yunxi.mes.module.heli.enums.CodeEnum.PROJECT_DELIVERY_ORDER; -import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.DELIVER_ORDER_NOT_EXISTS; -import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.INVALID_OPERATE; +import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.*; /** * 发货订单 Service 实现类 @@ -43,6 +52,12 @@ public class DeliverOrderServiceImpl implements DeliverOrderService { private DeliverOrderSubMapper deliverOrderSubMapper; @Resource private SerialNumberService serialNumberService; + @Resource + private ProjectOrderMapper projectOrderMapper; + @Resource + private ProjectOrderSubMapper projectOrderSubMapper; + @Resource + private CrossOrderStatusManager crossOrderStatusManager; @Override @Transactional(rollbackFor = Exception.class) @@ -60,9 +75,18 @@ public class DeliverOrderServiceImpl implements DeliverOrderService { if(createReqVO.getDeliverOrderSubs() != null && !createReqVO.getDeliverOrderSubs().isEmpty()){ createDeliverOrderSubList(deliverOrder.getId(), createReqVO.getDeliverOrderSubs()); } + if(createReqVO.getDeliverOrderOtherSubs() != null && !createReqVO.getDeliverOrderOtherSubs().isEmpty()){ + createDeliverOrderSubList(deliverOrder.getId(), createReqVO.getDeliverOrderOtherSubs()); + } + createReqVO.setId(deliverOrder.getId()).setCode(deliverOrder.getCode()); // 回写序列记录 serialNumberService.updateSerialNumber(serialNumberDO); + + OperateTypeEnum operateTypeEnum = OperateTypeEnum.valueOf(createReqVO.getActive()); + if(operateTypeEnum == OperateTypeEnum.DELIVER) { + crossOrderStatusManager.refreshProjectOrderDeliverStatus(createReqVO.getSaleOrderIds().split(",")); + } // 返回 return deliverOrder.getId(); } @@ -72,9 +96,56 @@ public class DeliverOrderServiceImpl implements DeliverOrderService { public void updateDeliverOrder(DeliverOrderSaveReqVO updateReqVO) { // 校验存在 DeliverOrderDO oldDO = validateDeliverOrderExists(updateReqVO.getId()); - if(!oldDO.canOperate(OperateTypeEnum.valueOf(updateReqVO.getActive()))){ + OperateTypeEnum operateTypeEnum = OperateTypeEnum.valueOf(updateReqVO.getActive()); + if(!oldDO.canOperate(operateTypeEnum)){ throw exception(INVALID_OPERATE); } + // 校验数据 不容许超额发货 + if(operateTypeEnum == OperateTypeEnum.DELIVER){ + List thisTimeSubs = updateReqVO.getDeliverOrderSubs(); + List thisTimeRelaSubList = thisTimeSubs.stream().filter(deliverOrderSubDO -> deliverOrderSubDO.getSaleOrderSubId() != null).collect(Collectors.toList()); + + if(!thisTimeRelaSubList.isEmpty()){ + // 锁定订单 + LambdaQueryWrapper projectQuery = new LambdaQueryWrapper<>(); + projectQuery.in(ProjectOrderDO::getId, updateReqVO.getSaleOrderIds().split(",")).last("FOR UPDATE"); + List projectOrderDOList = projectOrderMapper.selectList(projectQuery); + + // 状态判断 已发货不容许操作 + boolean anyoneDone = projectOrderDOList.stream().anyMatch(projectOrderDO -> { + return projectOrderDO.getOrderStatus().intValue() == ProjectOrderDeliverStatusEnum.ALL.getCode(); + }); + if(anyoneDone){ + throw exception(RELATION_PROJECT_ORDER_HAS_DONE); + } + + // 查询关联子项目信息判断额度 + Map> thisTimeSubsGroupBySaleSubId = thisTimeRelaSubList.stream().collect(Collectors.groupingBy(DeliverOrderSubDO::getSaleOrderSubId)); + List relaProjectOrderSubList = projectOrderSubMapper.selectBatchIds(thisTimeSubsGroupBySaleSubId.keySet()); + + // 查询历史发货信息 + MPJLambdaWrapper historyDeliveredSubQuery = new MPJLambdaWrapper<>(); + historyDeliveredSubQuery.selectAll(DeliverOrderSubDO.class) + .leftJoin(DeliverOrderDO.class, DeliverOrderDO::getId, DeliverOrderSubDO::getDeliveryOrderId) + .eq(DeliverOrderDO::getDeliverStatus, DeliverOrderStatusEnum.DELIVER.getCode()) + .in(DeliverOrderSubDO::getSaleOrderSubId, thisTimeSubsGroupBySaleSubId.keySet()); + List historyDeliveredSubList = deliverOrderSubMapper.selectList(historyDeliveredSubQuery); + Map> historyDeliveredSubsGroupBySaleSubId = historyDeliveredSubList.stream().collect(Collectors.groupingBy(DeliverOrderSubDO::getSaleOrderSubId)); + + // 关联额度-历史发货额度-本次发货额度 >= 0 则可通过 + boolean allDeliverable = relaProjectOrderSubList.stream().allMatch(relaSub -> { + int relaAmount = relaSub.getAmount(); + List historySubList = historyDeliveredSubsGroupBySaleSubId.get(relaSub.getId()); + int historyDeliveredAmount = historySubList == null || historySubList.isEmpty() ? 0 : historySubList.stream().mapToInt(DeliverOrderSubDO::getAmount).sum(); + int thisTimeAmount = thisTimeSubsGroupBySaleSubId.get(relaSub.getId()).get(0).getAmount(); + return relaAmount-historyDeliveredAmount-thisTimeAmount >= 0; + }); + if(!allDeliverable){ + throw exception(DELIVER_AMOUNT_OVERFLOW); + } + } + } + // 更新 DeliverOrderDO updateObj = BeanUtils.toBean(updateReqVO, DeliverOrderDO.class); updateObj.setDeliverStatus(DeliverOrderStatusEnum.valueOf(updateReqVO.getActive()).getCode()); @@ -82,7 +153,11 @@ public class DeliverOrderServiceImpl implements DeliverOrderService { updateReqVO.setDeliverStatus(updateObj.getDeliverStatus()); // 更新子表 - updateDeliverOrderSubList(updateReqVO.getId(), updateReqVO.getDeliverOrderSubs()); + updateDeliverOrderSubList(updateReqVO.getId(), updateReqVO.getDeliverOrderSubs(), updateReqVO.getDeliverOrderOtherSubs()); + + if(operateTypeEnum == OperateTypeEnum.DELIVER) { + crossOrderStatusManager.refreshProjectOrderDeliverStatus(updateReqVO.getSaleOrderIds().split(",")); + } } @Override @@ -140,10 +215,14 @@ public class DeliverOrderServiceImpl implements DeliverOrderService { deliverOrderSubMapper.insertBatch(list); } - private void updateDeliverOrderSubList(Long deliveryOrderId, List list) { + private void updateDeliverOrderSubList(Long deliveryOrderId, List list, @Valid List deliverOrderOtherSubs) { deleteDeliverOrderSubByDeliveryOrderId(deliveryOrderId); list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 createDeliverOrderSubList(deliveryOrderId, list); + if(deliverOrderOtherSubs != null || !deliverOrderOtherSubs.isEmpty()){ + deliverOrderOtherSubs.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createDeliverOrderSubList(deliveryOrderId, deliverOrderOtherSubs); + } } private void deleteDeliverOrderSubByDeliveryOrderId(Long deliveryOrderId) { diff --git a/mes-ui/mes-ui-admin-vue3/src/views/heli/deliverorder/detail.vue b/mes-ui/mes-ui-admin-vue3/src/views/heli/deliverorder/detail.vue index 11468955..d3b7fc82 100644 --- a/mes-ui/mes-ui-admin-vue3/src/views/heli/deliverorder/detail.vue +++ b/mes-ui/mes-ui-admin-vue3/src/views/heli/deliverorder/detail.vue @@ -117,7 +117,7 @@ - + @@ -202,7 +202,7 @@ - + @@ -285,7 +285,7 @@ + +