Commit 6be8ab8893a0b3b1db3f749315326ac5e6ee9a31

Authored by YunaiV
1 parent 4ec13fac

✨ feat(mes): 添加杂项入库单行分页功能及明细服务实现

Showing 27 changed files with 1368 additions and 12 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java
1 package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt; 1 package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO;
5 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineRespVO; 7 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineRespVO;
6 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; 8 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO;
7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO;
@@ -73,4 +75,12 @@ public class MesWmMiscReceiptLineController { @@ -73,4 +75,12 @@ public class MesWmMiscReceiptLineController {
73 return success(BeanUtils.toBean(list, MesWmMiscReceiptLineRespVO.class)); 75 return success(BeanUtils.toBean(list, MesWmMiscReceiptLineRespVO.class));
74 } 76 }
75 77
  78 + @GetMapping("/page")
  79 + @Operation(summary = "获得杂项入库单行分页")
  80 + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')")
  81 + public CommonResult<PageResult<MesWmMiscReceiptLineRespVO>> getMiscReceiptLinePage(@Valid MesWmMiscReceiptLinePageReqVO pageReqVO) {
  82 + PageResult<MesWmMiscReceiptLineDO> pageResult = miscReceiptLineService.getMiscReceiptLinePage(pageReqVO);
  83 + return success(BeanUtils.toBean(pageResult, MesWmMiscReceiptLineRespVO.class));
  84 + }
  85 +
76 } 86 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java
1 package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line; 1 package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.DecimalMin;
4 import jakarta.validation.constraints.NotNull; 5 import jakarta.validation.constraints.NotNull;
5 import lombok.Data; 6 import lombok.Data;
6 7
@@ -24,7 +25,7 @@ public class MesWmMiscReceiptLineSaveReqVO { @@ -24,7 +25,7 @@ public class MesWmMiscReceiptLineSaveReqVO {
24 25
25 @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") 26 @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
26 @NotNull(message = "入库数量不能为空") 27 @NotNull(message = "入库数量不能为空")
27 - // TODO @AI:最小是 0.01 28 + @DecimalMin(value = "0.01", message = "入库数量不能小于 0.01")
28 private BigDecimal quantity; 29 private BigDecimal quantity;
29 30
30 @Schema(description = "批次号", example = "BATCH20260301") 31 @Schema(description = "批次号", example = "BATCH20260301")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;
  8 +import com.baomidou.mybatisplus.annotation.KeySequence;
  9 +import com.baomidou.mybatisplus.annotation.TableId;
  10 +import com.baomidou.mybatisplus.annotation.TableName;
  11 +import lombok.*;
  12 +
  13 +import java.math.BigDecimal;
  14 +import java.time.LocalDateTime;
  15 +
  16 +/**
  17 + * MES 杂项入库明细 DO
  18 + */
  19 +@TableName("mes_wm_misc_receipt_detail")
  20 +@KeySequence("mes_wm_misc_receipt_detail_seq")
  21 +@Data
  22 +@EqualsAndHashCode(callSuper = true)
  23 +@ToString(callSuper = true)
  24 +@Builder
  25 +@NoArgsConstructor
  26 +@AllArgsConstructor
  27 +public class MesWmMiscReceiptDetailDO extends BaseDO {
  28 +
  29 + /**
  30 + * 编号
  31 + */
  32 + @TableId
  33 + private Long id;
  34 + /**
  35 + * 入库单ID
  36 + *
  37 + * 关联 {@link MesWmMiscReceiptDO#getId()}
  38 + */
  39 + private Long receiptId;
  40 + /**
  41 + * 行ID
  42 + *
  43 + * 关联 {@link MesWmMiscReceiptLineDO#getId()}
  44 + */
  45 + private Long lineId;
  46 + /**
  47 + * 物料ID
  48 + *
  49 + * 关联 {@link MesMdItemDO#getId()}
  50 + */
  51 + private Long itemId;
  52 + /**
  53 + * 入库数量
  54 + */
  55 + private BigDecimal quantity;
  56 + /**
  57 + * 批次号
  58 + */
  59 + private String batchCode;
  60 + /**
  61 + * 仓库ID
  62 + *
  63 + * 关联 {@link MesWmWarehouseDO#getId()}
  64 + */
  65 + private Long warehouseId;
  66 + /**
  67 + * 库区ID
  68 + *
  69 + * 关联 {@link MesWmWarehouseLocationDO#getId()}
  70 + */
  71 + private Long locationId;
  72 + /**
  73 + * 库位ID
  74 + *
  75 + * 关联 {@link MesWmWarehouseAreaDO#getId()}
  76 + */
  77 + private Long areaId;
  78 + /**
  79 + * 生产日期
  80 + */
  81 + private LocalDateTime productionDate;
  82 + /**
  83 + * 有效期
  84 + */
  85 + private LocalDateTime expireDate;
  86 + /**
  87 + * 生产批号
  88 + */
  89 + private String productionBatchNumber;
  90 + /**
  91 + * 备注
  92 + */
  93 + private String remark;
  94 +
  95 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
  5 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum;
  6 +import com.baomidou.mybatisplus.annotation.KeySequence;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +import java.time.LocalDateTime;
  12 +
  13 +/**
  14 + * MES 外协发料单 DO
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@TableName("mes_wm_outsource_issue")
  19 +@KeySequence("mes_wm_outsource_issue_seq")
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +@Builder
  24 +@NoArgsConstructor
  25 +@AllArgsConstructor
  26 +public class MesWmOutsourceIssueDO extends BaseDO {
  27 +
  28 + /**
  29 + * 发料单ID
  30 + */
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 发料单编号
  35 + */
  36 + private String code;
  37 + /**
  38 + * 发料单名称
  39 + */
  40 + private String name;
  41 + /**
  42 + * 供应商ID
  43 + *
  44 + * 关联 {@link MesMdVendorDO#getId()}
  45 + */
  46 + private Long vendorId;
  47 + // TODO @AI:去掉冗余的 vendorCode、vendorName 字段
  48 + /**
  49 + * 供应商编码
  50 + */
  51 + private String vendorCode;
  52 + /**
  53 + * 供应商名称
  54 + */
  55 + private String vendorName;
  56 + // TODO @AI:去掉冗余的 workorderCode、workorderName 字段
  57 + // TODO @AI:拼写不对;应该是 workOrderId;
  58 + /**
  59 + * 生产工单ID
  60 + */
  61 + private Long workorderId;
  62 + /**
  63 + * 生产工单编码
  64 + */
  65 + private String workorderCode;
  66 + /**
  67 + * 生产工单名称
  68 + */
  69 + private String workorderName;
  70 + /**
  71 + * 发料日期
  72 + */
  73 + private LocalDateTime issueDate;
  74 + /**
  75 + * 单据状态
  76 + *
  77 + * 枚举 {@link MesWmOutsourceIssueStatusEnum}
  78 + */
  79 + private Integer status;
  80 + /**
  81 + * 备注
  82 + */
  83 + private String remark;
  84 +
  85 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
  6 +import com.baomidou.mybatisplus.annotation.KeySequence;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +import java.math.BigDecimal;
  12 +
  13 +/**
  14 + * MES 外协发料单明细 DO
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@TableName("mes_wm_outsource_issue_detail")
  19 +@KeySequence("mes_wm_outsource_issue_detail_seq")
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +@Builder
  24 +@NoArgsConstructor
  25 +@AllArgsConstructor
  26 +public class MesWmOutsourceIssueDetailDO extends BaseDO {
  27 +
  28 + /**
  29 + * 明细ID
  30 + */
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 行ID
  35 + *
  36 + * 关联 {@link MesWmOutsourceIssueLineDO#getId()}
  37 + */
  38 + private Long lineId;
  39 + /**
  40 + * 发料单ID
  41 + *
  42 + * 关联 {@link MesWmOutsourceIssueDO#getId()}
  43 + */
  44 + private Long issueId;
  45 + /**
  46 + * 库存ID
  47 + */
  48 + private Long materialStockId;
  49 + /**
  50 + * 物料ID
  51 + *
  52 + * 关联 {@link MesMdItemDO#getId()}
  53 + */
  54 + private Long itemId;
  55 + /**
  56 + * 数量
  57 + */
  58 + private BigDecimal quantity;
  59 + /**
  60 + * 批次ID
  61 + */
  62 + private Long batchId;
  63 + /**
  64 + * 仓库ID
  65 + *
  66 + * 关联 {@link MesWmWarehouseDO#getId()}
  67 + */
  68 + private Long warehouseId;
  69 + /**
  70 + * 库位ID
  71 + */
  72 + private Long locationId;
  73 + /**
  74 + * 库区ID
  75 + */
  76 + private Long areaId;
  77 + /**
  78 + * 备注
  79 + */
  80 + private String remark;
  81 +
  82 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.math.BigDecimal;
  11 +
  12 +/**
  13 + * MES 外协发料单行 DO
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@TableName("mes_wm_outsource_issue_line")
  18 +@KeySequence("mes_wm_outsource_issue_line_seq")
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class MesWmOutsourceIssueLineDO extends BaseDO {
  26 +
  27 + /**
  28 + * 行ID
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 发料单ID
  34 + *
  35 + * 关联 {@link MesWmOutsourceIssueDO#getId()}
  36 + */
  37 + private Long issueId;
  38 + /**
  39 + * 库存ID
  40 + */
  41 + private Long materialStockId;
  42 + /**
  43 + * 物料ID
  44 + *
  45 + * 关联 {@link MesMdItemDO#getId()}
  46 + */
  47 + private Long itemId;
  48 + /**
  49 + * 发料数量
  50 + */
  51 + private BigDecimal quantity;
  52 + /**
  53 + * 批次ID
  54 + */
  55 + private Long batchId;
  56 + /**
  57 + * 备注
  58 + */
  59 + private String remark;
  60 +
  61 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * MES 杂项入库明细 Mapper
  11 + */
  12 +@Mapper
  13 +public interface MesWmMiscReceiptDetailMapper extends BaseMapperX<MesWmMiscReceiptDetailDO> {
  14 +
  15 + default List<MesWmMiscReceiptDetailDO> selectListByLineId(Long lineId) {
  16 + return selectList(MesWmMiscReceiptDetailDO::getLineId, lineId);
  17 + }
  18 +
  19 + default List<MesWmMiscReceiptDetailDO> selectListByReceiptId(Long receiptId) {
  20 + return selectList(MesWmMiscReceiptDetailDO::getReceiptId, receiptId);
  21 + }
  22 +
  23 + default void deleteByReceiptId(Long receiptId) {
  24 + delete(MesWmMiscReceiptDetailDO::getReceiptId, receiptId);
  25 + }
  26 +
  27 + default void deleteByLineId(Long lineId) {
  28 + delete(MesWmMiscReceiptDetailDO::getLineId, lineId);
  29 + }
  30 +
  31 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java
1 package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; 1 package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; 7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO;
6 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
7 9
@@ -26,4 +28,10 @@ public interface MesWmMiscReceiptLineMapper extends BaseMapperX&lt;MesWmMiscReceipt @@ -26,4 +28,10 @@ public interface MesWmMiscReceiptLineMapper extends BaseMapperX&lt;MesWmMiscReceipt
26 .eq(MesWmMiscReceiptLineDO::getReceiptId, receiptId)); 28 .eq(MesWmMiscReceiptLineDO::getReceiptId, receiptId));
27 } 29 }
28 30
  31 + default PageResult<MesWmMiscReceiptLineDO> selectPage(MesWmMiscReceiptLinePageReqVO pageReqVO) {
  32 + return selectPage(pageReqVO, new LambdaQueryWrapperX<MesWmMiscReceiptLineDO>()
  33 + .eq(MesWmMiscReceiptLineDO::getReceiptId, pageReqVO.getReceiptId())
  34 + .orderByAsc(MesWmMiscReceiptLineDO::getId));
  35 + }
  36 +
29 } 37 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * MES 外协发料单明细 Mapper
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Mapper
  15 +public interface MesWmOutsourceIssueDetailMapper extends BaseMapperX<MesWmOutsourceIssueDetailDO> {
  16 +
  17 + default List<MesWmOutsourceIssueDetailDO> selectListByIssueId(Long issueId) {
  18 + return selectList(MesWmOutsourceIssueDetailDO::getIssueId, issueId);
  19 + }
  20 +
  21 + default List<MesWmOutsourceIssueDetailDO> selectListByLineId(Long lineId) {
  22 + return selectList(MesWmOutsourceIssueDetailDO::getLineId, lineId);
  23 + }
  24 +
  25 + default void deleteByIssueId(Long issueId) {
  26 + delete(MesWmOutsourceIssueDetailDO::getIssueId, issueId);
  27 + }
  28 +
  29 + default void deleteByLineId(Long lineId) {
  30 + delete(MesWmOutsourceIssueDetailDO::getLineId, lineId);
  31 + }
  32 +
  33 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * MES 外协发料单行 Mapper
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Mapper
  18 +public interface MesWmOutsourceIssueLineMapper extends BaseMapperX<MesWmOutsourceIssueLineDO> {
  19 +
  20 + default PageResult<MesWmOutsourceIssueLineDO> selectPage(MesWmOutsourceIssueLinePageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmOutsourceIssueLineDO>()
  22 + .eqIfPresent(MesWmOutsourceIssueLineDO::getIssueId, reqVO.getIssueId())
  23 + .orderByDesc(MesWmOutsourceIssueLineDO::getId));
  24 + }
  25 +
  26 + default List<MesWmOutsourceIssueLineDO> selectListByIssueId(Long issueId) {
  27 + return selectList(MesWmOutsourceIssueLineDO::getIssueId, issueId);
  28 + }
  29 +
  30 + default void deleteByIssueId(Long issueId) {
  31 + delete(MesWmOutsourceIssueLineDO::getIssueId, issueId);
  32 + }
  33 +
  34 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +/**
  11 + * MES 外协发料单 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Mapper
  16 +public interface MesWmOutsourceIssueMapper extends BaseMapperX<MesWmOutsourceIssueDO> {
  17 +
  18 + default PageResult<MesWmOutsourceIssueDO> selectPage(MesWmOutsourceIssuePageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmOutsourceIssueDO>()
  20 + .likeIfPresent(MesWmOutsourceIssueDO::getCode, reqVO.getCode())
  21 + .likeIfPresent(MesWmOutsourceIssueDO::getName, reqVO.getName())
  22 + .eqIfPresent(MesWmOutsourceIssueDO::getVendorId, reqVO.getVendorId())
  23 + .eqIfPresent(MesWmOutsourceIssueDO::getWorkorderId, reqVO.getWorkorderId())
  24 + .likeIfPresent(MesWmOutsourceIssueDO::getWorkorderCode, reqVO.getWorkorderCode())
  25 + .betweenIfPresent(MesWmOutsourceIssueDO::getIssueDate, reqVO.getIssueDate())
  26 + .eqIfPresent(MesWmOutsourceIssueDO::getStatus, reqVO.getStatus())
  27 + .orderByDesc(MesWmOutsourceIssueDO::getId));
  28 + }
  29 +
  30 + default MesWmOutsourceIssueDO selectByCode(String code) {
  31 + return selectOne(MesWmOutsourceIssueDO::getCode, code);
  32 + }
  33 +
  34 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -466,6 +466,18 @@ public interface ErrorCodeConstants { @@ -466,6 +466,18 @@ public interface ErrorCodeConstants {
466 ErrorCode WM_MISC_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_715_100, "杂项出库单行不存在"); 466 ErrorCode WM_MISC_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_715_100, "杂项出库单行不存在");
467 ErrorCode WM_MISC_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_715_200, "杂项出库单明细不存在"); 467 ErrorCode WM_MISC_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_715_200, "杂项出库单明细不存在");
468 468
  469 + // ========== MES 仓库管理-杂项入库单(1-040-716-000) ==========
  470 + ErrorCode WM_MISC_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_716_000, "杂项入库单不存在");
  471 + ErrorCode WM_MISC_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_716_001, "杂项入库单编码已存在");
  472 + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_716_002, "只有草稿状态才允许此操作");
  473 + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_APPROVED = new ErrorCode(1_040_716_003, "只有已审批状态才允许执行入库");
  474 + ErrorCode WM_MISC_RECEIPT_NO_LINE = new ErrorCode(1_040_716_004, "至少需要一条行项目");
  475 + ErrorCode WM_MISC_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_716_005, "已完成或已取消的入库单不允许取消");
  476 + ErrorCode WM_MISC_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_716_100, "杂项入库单行不存在");
  477 + ErrorCode WM_MISC_RECEIPT_WAREHOUSE_REQUIRED = new ErrorCode(1_040_716_101, "仓库不能为空");
  478 + ErrorCode WM_MISC_RECEIPT_QUANTITY_INVALID = new ErrorCode(1_040_716_102, "入库数量必须大于 0");
  479 + ErrorCode WM_MISC_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_716_200, "杂项入库单明细不存在");
  480 +
469 // ========== MES 仓库管理-发货通知单(1-040-720-000) ========== 481 // ========== MES 仓库管理-发货通知单(1-040-720-000) ==========
470 ErrorCode WM_SALES_NOTICE_NOT_EXISTS = new ErrorCode(1_040_720_000, "发货通知单不存在"); 482 ErrorCode WM_SALES_NOTICE_NOT_EXISTS = new ErrorCode(1_040_720_000, "发货通知单不存在");
471 ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复"); 483 ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.wm;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Getter;
  7 +
  8 +import java.util.Arrays;
  9 +
  10 +/**
  11 + * MES 外协发料单状态枚举
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Getter
  16 +@AllArgsConstructor
  17 +public enum MesWmOutsourceIssueStatusEnum implements ArrayValuable<Integer> {
  18 +
  19 + /**
  20 + * 草稿
  21 + */
  22 + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"),
  23 + // TODO @AI:状态缺失了;
  24 + /**
  25 + * 已完成
  26 + */
  27 + FINISHED(MesOrderStatusConstants.FINISHED, "已完成");
  28 +
  29 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceIssueStatusEnum::getStatus).toArray(Integer[]::new);
  30 +
  31 + /**
  32 + * 状态值
  33 + */
  34 + private final Integer status;
  35 + /**
  36 + * 状态名
  37 + */
  38 + private final String name;
  39 +
  40 + @Override
  41 + public Integer[] array() {
  42 + return ARRAYS;
  43 + }
  44 +
  45 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.wm;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Getter;
  7 +
  8 +import java.util.Arrays;
  9 +
  10 +/**
  11 + * MES 委外收货单状态枚举
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Getter
  16 +@AllArgsConstructor
  17 +public enum MesWmOutsourceReceiptStatusEnum implements ArrayValuable<Integer> {
  18 +
  19 + // TODO @AI:需要 @对应的状态;参考 /Users/yunai/Java/yudao-all-in-one/ruoyi-vue-pro/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueStatusEnum.java 里的逻辑;
  20 + /**
  21 + * 准备中
  22 + */
  23 + PREPARE(MesOrderStatusConstants.PREPARE, "准备中"),
  24 + /**
  25 + * 审批中
  26 + */
  27 + APPROVING(MesOrderStatusConstants.APPROVING, "审批中"),
  28 + /**
  29 + * 已审批
  30 + */
  31 + APPROVED(MesOrderStatusConstants.APPROVED, "已审批"),
  32 + /**
  33 + * 已完成
  34 + */
  35 + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"),
  36 + /**
  37 + * 已取消
  38 + */
  39 + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消");
  40 +
  41 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceReceiptStatusEnum::getStatus).toArray(Integer[]::new);
  42 +
  43 + /**
  44 + * 状态值
  45 + */
  46 + private final Integer status;
  47 + /**
  48 + * 状态名
  49 + */
  50 + private final String name;
  51 +
  52 + @Override
  53 + public Integer[] array() {
  54 + return ARRAYS;
  55 + }
  56 +
  57 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt;
  2 +
  3 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO;
  4 +
  5 +/**
  6 + * MES 杂项入库明细 Service 接口
  7 + */
  8 +public interface MesWmMiscReceiptDetailService {
  9 +
  10 + /**
  11 + * 创建杂项入库明细
  12 + *
  13 + * @param createReqVO 创建信息
  14 + * @return 编号
  15 + */
  16 + Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO);
  17 +
  18 + /**
  19 + * 更新杂项入库明细
  20 + *
  21 + * @param updateReqVO 更新信息
  22 + */
  23 + void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO);
  24 +
  25 + /**
  26 + * 删除杂项入库明细(根据入库单ID)
  27 + *
  28 + * @param receiptId 入库单ID
  29 + */
  30 + void deleteMiscReceiptDetailByReceiptId(Long receiptId);
  31 +
  32 + /**
  33 + * 删除杂项入库明细(根据行ID)
  34 + *
  35 + * @param lineId 行ID
  36 + */
  37 + void deleteMiscReceiptDetailByLineId(Long lineId);
  38 +
  39 + /**
  40 + * 校验杂项入库明细是否存在
  41 + *
  42 + * @param id 编号
  43 + */
  44 + void validateMiscReceiptDetailExists(Long id);
  45 +
  46 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO;
  7 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptDetailMapper;
  8 +import jakarta.annotation.Resource;
  9 +import org.springframework.stereotype.Service;
  10 +import org.springframework.validation.annotation.Validated;
  11 +
  12 +import java.util.List;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  15 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_RECEIPT_DETAIL_NOT_EXISTS;
  16 +
  17 +/**
  18 + * MES 杂项入库明细 Service 实现类
  19 + */
  20 +@Service
  21 +@Validated
  22 +public class MesWmMiscReceiptDetailServiceImpl implements MesWmMiscReceiptDetailService {
  23 +
  24 + @Resource
  25 + private MesWmMiscReceiptDetailMapper receiptDetailMapper;
  26 +
  27 + @Override
  28 + public Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO) {
  29 + MesWmMiscReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmMiscReceiptDetailDO.class);
  30 + detail.setId(null); // 清空 id,让数据库自动生成
  31 + detail.setLineId(createReqVO.getId()); // VO 的 id 就是 lineId
  32 + receiptDetailMapper.insert(detail);
  33 + return detail.getId();
  34 + }
  35 +
  36 + @Override
  37 + public void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO) {
  38 + // 基于 lineId 查询唯一的 detail 记录(VO 的 id 字段是 lineId)
  39 + List<MesWmMiscReceiptDetailDO> details = receiptDetailMapper.selectListByLineId(updateReqVO.getId());
  40 + if (CollUtil.isEmpty(details)) {
  41 + return;
  42 + }
  43 +
  44 + // 更新 detail(应该只有一条记录)
  45 + MesWmMiscReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptDetailDO.class);
  46 + updateObj.setId(details.get(0).getId()); // 使用查询到的 detail id
  47 + updateObj.setLineId(updateReqVO.getId()); // VO 的 id 就是 lineId
  48 + receiptDetailMapper.updateById(updateObj);
  49 + }
  50 +
  51 + @Override
  52 + public void deleteMiscReceiptDetailByReceiptId(Long receiptId) {
  53 + receiptDetailMapper.deleteByReceiptId(receiptId);
  54 + }
  55 +
  56 + @Override
  57 + public void deleteMiscReceiptDetailByLineId(Long lineId) {
  58 + receiptDetailMapper.deleteByLineId(lineId);
  59 + }
  60 +
  61 + @Override
  62 + public void validateMiscReceiptDetailExists(Long id) {
  63 + if (receiptDetailMapper.selectById(id) == null) {
  64 + throw exception(WM_MISC_RECEIPT_DETAIL_NOT_EXISTS);
  65 + }
  66 + }
  67 +
  68 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java
1 package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; 1 package cn.iocoder.yudao.module.mes.service.wm.miscreceipt;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO;
3 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO;
4 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO;
5 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
@@ -50,6 +52,14 @@ public interface MesWmMiscReceiptLineService { @@ -50,6 +52,14 @@ public interface MesWmMiscReceiptLineService {
50 List<MesWmMiscReceiptLineDO> getMiscReceiptLineListByReceiptId(Long receiptId); 52 List<MesWmMiscReceiptLineDO> getMiscReceiptLineListByReceiptId(Long receiptId);
51 53
52 /** 54 /**
  55 + * 获得杂项入库单行分页
  56 + *
  57 + * @param pageReqVO 分页参数
  58 + * @return 杂项入库单行分页
  59 + */
  60 + PageResult<MesWmMiscReceiptLineDO> getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO);
  61 +
  62 + /**
53 * 校验杂项入库单行存在 63 * 校验杂项入库单行存在
54 * 64 *
55 * @param id 编号 65 * @param id 编号
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java
1 package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; 1 package cn.iocoder.yudao.module.mes.service.wm.miscreceipt;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO;
4 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; 7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO;
6 import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptLineMapper; 8 import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptLineMapper;
  9 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  10 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
7 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
  12 +import org.springframework.context.annotation.Lazy;
8 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
  14 +import org.springframework.transaction.annotation.Transactional;
9 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
10 16
11 import java.util.List; 17 import java.util.List;
@@ -23,36 +29,69 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ @@ -23,36 +29,69 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ
23 @Resource 29 @Resource
24 private MesWmMiscReceiptLineMapper miscReceiptLineMapper; 30 private MesWmMiscReceiptLineMapper miscReceiptLineMapper;
25 31
  32 + @Resource
  33 + @Lazy
  34 + private MesWmMiscReceiptService miscReceiptService;
  35 + @Resource
  36 + @Lazy
  37 + private MesWmMiscReceiptDetailService miscReceiptDetailService;
  38 + @Resource
  39 + private MesMdItemService itemService;
  40 + @Resource
  41 + private MesWmWarehouseAreaService warehouseAreaService;
  42 +
26 @Override 43 @Override
  44 + @Transactional(rollbackFor = Exception.class)
27 public Long createMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO createReqVO) { 45 public Long createMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO createReqVO) {
28 - // TODO @AI:物料存在;lineId 可编辑; 46 + // 1.1 校验父单据存在且为可编辑状态
  47 + miscReceiptService.validateMiscReceiptEditable(createReqVO.getReceiptId());
  48 + // 1.2 校验物料存在
  49 + itemService.validateItemExists(createReqVO.getItemId());
  50 + // 1.3 校验仓库、库区、库位的父子关系
  51 + warehouseAreaService.validateWarehouseAreaExists(createReqVO.getWarehouseId(),
  52 + createReqVO.getLocationId(), createReqVO.getAreaId());
29 53
30 - // 插入 54 + // 2. 新增行
31 MesWmMiscReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscReceiptLineDO.class); 55 MesWmMiscReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscReceiptLineDO.class);
32 miscReceiptLineMapper.insert(line); 56 miscReceiptLineMapper.insert(line);
33 - // TODO @AI:还是需要新增一个 detail 表;类似别的 line + detail 的设计;1)create 时,新增;2)update 时,更新;3)delete 时,删除; 57 +
  58 + // 3. 自动创建明细
  59 + createReqVO.setId(line.getId());
  60 + miscReceiptDetailService.createMiscReceiptDetail(createReqVO);
34 return line.getId(); 61 return line.getId();
35 } 62 }
36 63
37 @Override 64 @Override
  65 + @Transactional(rollbackFor = Exception.class)
38 public void updateMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO updateReqVO) { 66 public void updateMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO updateReqVO) {
39 - // 校验存在  
40 - validateMiscReceiptLineExists(updateReqVO.getId());  
41 - // TODO @AI:物料存在;lineId 可编辑; 67 + // 1.1 校验存在
  68 + MesWmMiscReceiptLineDO line = validateMiscReceiptLineExists(updateReqVO.getId());
  69 + // 1.2 校验父单据存在且为可编辑状态
  70 + miscReceiptService.validateMiscReceiptEditable(line.getReceiptId());
  71 + // 1.3 校验物料存在
  72 + itemService.validateItemExists(updateReqVO.getItemId());
  73 + // 1.4 校验仓库、库区、库位的父子关系
  74 + warehouseAreaService.validateWarehouseAreaExists(updateReqVO.getWarehouseId(),
  75 + updateReqVO.getLocationId(), updateReqVO.getAreaId());
42 76
43 - // 更新 77 + // 2. 更新行
44 MesWmMiscReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptLineDO.class); 78 MesWmMiscReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptLineDO.class);
45 miscReceiptLineMapper.updateById(updateObj); 79 miscReceiptLineMapper.updateById(updateObj);
  80 +
  81 + // 3. 更新明细(基于行信息)
  82 + miscReceiptDetailService.updateMiscReceiptDetail(updateReqVO);
46 } 83 }
47 84
48 @Override 85 @Override
  86 + @Transactional(rollbackFor = Exception.class)
49 public void deleteMiscReceiptLine(Long id) { 87 public void deleteMiscReceiptLine(Long id) {
50 - // TODO @AI:lineId 存在 + 可编辑;  
51 // 校验存在 88 // 校验存在
52 validateMiscReceiptLineExists(id); 89 validateMiscReceiptLineExists(id);
53 90
54 - // 删除 91 + // 删除行
55 miscReceiptLineMapper.deleteById(id); 92 miscReceiptLineMapper.deleteById(id);
  93 + // 删除明细
  94 + miscReceiptDetailService.deleteMiscReceiptDetailByLineId(id);
56 } 95 }
57 96
58 @Override 97 @Override
@@ -66,6 +105,11 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ @@ -66,6 +105,11 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ
66 } 105 }
67 106
68 @Override 107 @Override
  108 + public PageResult<MesWmMiscReceiptLineDO> getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO) {
  109 + return miscReceiptLineMapper.selectPage(pageReqVO);
  110 + }
  111 +
  112 + @Override
69 public MesWmMiscReceiptLineDO validateMiscReceiptLineExists(Long id) { 113 public MesWmMiscReceiptLineDO validateMiscReceiptLineExists(Long id) {
70 MesWmMiscReceiptLineDO line = miscReceiptLineMapper.selectById(id); 114 MesWmMiscReceiptLineDO line = miscReceiptLineMapper.selectById(id);
71 if (line == null) { 115 if (line == null) {
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java
@@ -80,4 +80,11 @@ public interface MesWmMiscReceiptService { @@ -80,4 +80,11 @@ public interface MesWmMiscReceiptService {
80 */ 80 */
81 MesWmMiscReceiptDO validateMiscReceiptExists(Long id); 81 MesWmMiscReceiptDO validateMiscReceiptExists(Long id);
82 82
  83 + /**
  84 + * 校验杂项入库单是否可编辑(存在且为草稿状态)
  85 + *
  86 + * @param id 编号
  87 + */
  88 + void validateMiscReceiptEditable(Long id);
  89 +
83 } 90 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java
@@ -38,6 +38,9 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { @@ -38,6 +38,9 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService {
38 private MesWmMiscReceiptLineMapper miscReceiptLineMapper; 38 private MesWmMiscReceiptLineMapper miscReceiptLineMapper;
39 39
40 @Resource 40 @Resource
  41 + private MesWmMiscReceiptDetailService miscReceiptDetailService;
  42 +
  43 + @Resource
41 private MesWmMaterialStockService materialStockService; 44 private MesWmMaterialStockService materialStockService;
42 45
43 @Override 46 @Override
@@ -70,6 +73,8 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { @@ -70,6 +73,8 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService {
70 // 校验存在 + 草稿状态 73 // 校验存在 + 草稿状态
71 validateMiscReceiptExistsAndPrepare(id); 74 validateMiscReceiptExistsAndPrepare(id);
72 75
  76 + // 级联删除明细
  77 + miscReceiptDetailService.deleteMiscReceiptDetailByReceiptId(id);
73 // 级联删除行 78 // 级联删除行
74 miscReceiptLineMapper.deleteByReceiptId(id); 79 miscReceiptLineMapper.deleteByReceiptId(id);
75 // 删除主表 80 // 删除主表
@@ -158,8 +163,6 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { @@ -158,8 +163,6 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService {
158 return receipt; 163 return receipt;
159 } 164 }
160 165
161 - // ==================== 私有方法 ====================  
162 -  
163 private void validateCodeUnique(Long id, String code) { 166 private void validateCodeUnique(Long id, String code) {
164 MesWmMiscReceiptDO receipt = miscReceiptMapper.selectByCode(code); 167 MesWmMiscReceiptDO receipt = miscReceiptMapper.selectByCode(code);
165 if (receipt == null) { 168 if (receipt == null) {
@@ -178,4 +181,13 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { @@ -178,4 +181,13 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService {
178 return receipt; 181 return receipt;
179 } 182 }
180 183
  184 + /**
  185 + * 校验入库单是否可编辑(存在且为草稿状态)
  186 + *
  187 + * @param id 入库单ID
  188 + */
  189 + public void validateMiscReceiptEditable(Long id) {
  190 + validateMiscReceiptExistsAndPrepare(id);
  191 + }
  192 +
181 } 193 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO;
  5 +import jakarta.validation.Valid;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * MES 外协发料单明细 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesWmOutsourceIssueDetailService {
  15 +
  16 + /**
  17 + * 创建外协发料单明细
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 修改外协发料单明细
  26 + *
  27 + * @param updateReqVO 修改信息
  28 + */
  29 + void updateOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除外协发料单明细
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deleteOutsourceIssueDetail(Long id);
  37 +
  38 + /**
  39 + * 获得外协发料单明细
  40 + *
  41 + * @param id 编号
  42 + * @return 外协发料单明细
  43 + */
  44 + MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id);
  45 +
  46 + /**
  47 + * 获得外协发料单明细列表
  48 + *
  49 + * @param issueId 发料单ID
  50 + * @return 外协发料单明细列表
  51 + */
  52 + List<MesWmOutsourceIssueDetailDO> getOutsourceIssueDetailListByIssueId(Long issueId);
  53 +
  54 + /**
  55 + * 获得外协发料单明细列表
  56 + *
  57 + * @param lineId 行ID
  58 + * @return 外协发料单明细列表
  59 + */
  60 + List<MesWmOutsourceIssueDetailDO> getOutsourceIssueDetailListByLineId(Long lineId);
  61 +
  62 + /**
  63 + * 删除外协发料单明细
  64 + *
  65 + * @param issueId 发料单ID
  66 + */
  67 + void deleteOutsourceIssueDetailByIssueId(Long issueId);
  68 +
  69 + /**
  70 + * 删除外协发料单明细
  71 + *
  72 + * @param lineId 行ID
  73 + */
  74 + void deleteOutsourceIssueDetailByLineId(Long lineId);
  75 +
  76 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO;
  6 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueDetailMapper;
  7 +import jakarta.annotation.Resource;
  8 +import org.springframework.stereotype.Service;
  9 +import org.springframework.validation.annotation.Validated;
  10 +
  11 +import java.util.List;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  14 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS;
  15 +
  16 +/**
  17 + * MES 外协发料单明细 Service 实现类
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@Service
  22 +@Validated
  23 +public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssueDetailService {
  24 +
  25 + @Resource
  26 + private MesWmOutsourceIssueDetailMapper outsourceIssueDetailMapper;
  27 +
  28 + @Override
  29 + public Long createOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO createReqVO) {
  30 + // TODO @AI:校验关联的 issueId;
  31 + // TODO AI校验关联的 itemId;
  32 +
  33 + // 插入
  34 + MesWmOutsourceIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDetailDO.class);
  35 + outsourceIssueDetailMapper.insert(detail);
  36 + return detail.getId();
  37 + }
  38 +
  39 + @Override
  40 + public void updateOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO updateReqVO) {
  41 + // 校验存在
  42 + validateOutsourceIssueDetailExists(updateReqVO.getId());
  43 + // TODO @AI:校验关联的 issueId;
  44 + // TODO AI校验关联的 itemId;
  45 +
  46 + // 更新
  47 + MesWmOutsourceIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDetailDO.class);
  48 + outsourceIssueDetailMapper.updateById(updateObj);
  49 + }
  50 +
  51 + @Override
  52 + public void deleteOutsourceIssueDetail(Long id) {
  53 + // 校验存在
  54 + validateOutsourceIssueDetailExists(id);
  55 + // 删除
  56 + outsourceIssueDetailMapper.deleteById(id);
  57 + }
  58 +
  59 + @Override
  60 + public MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id) {
  61 + return outsourceIssueDetailMapper.selectById(id);
  62 + }
  63 +
  64 + @Override
  65 + public List<MesWmOutsourceIssueDetailDO> getOutsourceIssueDetailListByIssueId(Long issueId) {
  66 + return outsourceIssueDetailMapper.selectListByIssueId(issueId);
  67 + }
  68 +
  69 + @Override
  70 + public List<MesWmOutsourceIssueDetailDO> getOutsourceIssueDetailListByLineId(Long lineId) {
  71 + return outsourceIssueDetailMapper.selectListByLineId(lineId);
  72 + }
  73 +
  74 + @Override
  75 + public void deleteOutsourceIssueDetailByIssueId(Long issueId) {
  76 + outsourceIssueDetailMapper.deleteByIssueId(issueId);
  77 + }
  78 +
  79 + @Override
  80 + public void deleteOutsourceIssueDetailByLineId(Long lineId) {
  81 + outsourceIssueDetailMapper.deleteByLineId(lineId);
  82 + }
  83 +
  84 + private void validateOutsourceIssueDetailExists(Long id) {
  85 + if (outsourceIssueDetailMapper.selectById(id) == null) {
  86 + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS);
  87 + }
  88 + }
  89 +
  90 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * MES 外协发料单行 Service 接口
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public interface MesWmOutsourceIssueLineService {
  17 +
  18 + /**
  19 + * 创建外协发料单行
  20 + *
  21 + * @param createReqVO 创建信息
  22 + * @return 编号
  23 + */
  24 + Long createOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO createReqVO);
  25 +
  26 + /**
  27 + * 修改外协发料单行
  28 + *
  29 + * @param updateReqVO 修改信息
  30 + */
  31 + void updateOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO updateReqVO);
  32 +
  33 + /**
  34 + * 删除外协发料单行
  35 + *
  36 + * @param id 编号
  37 + */
  38 + void deleteOutsourceIssueLine(Long id);
  39 +
  40 + /**
  41 + * 获得外协发料单行
  42 + *
  43 + * @param id 编号
  44 + * @return 外协发料单行
  45 + */
  46 + MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id);
  47 +
  48 + /**
  49 + * 获得外协发料单行分页
  50 + *
  51 + * @param pageReqVO 分页参数
  52 + * @return 外协发料单行分页
  53 + */
  54 + PageResult<MesWmOutsourceIssueLineDO> getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO);
  55 +
  56 + /**
  57 + * 获得外协发料单行列表
  58 + *
  59 + * @param issueId 发料单ID
  60 + * @return 外协发料单行列表
  61 + */
  62 + List<MesWmOutsourceIssueLineDO> getOutsourceIssueLineListByIssueId(Long issueId);
  63 +
  64 + /**
  65 + * 删除外协发料单行
  66 + *
  67 + * @param issueId 发料单ID
  68 + */
  69 + void deleteOutsourceIssueLineByIssueId(Long issueId);
  70 +
  71 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO;
  8 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueLineMapper;
  9 +import jakarta.annotation.Resource;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
  12 +
  13 +import java.util.List;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  16 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS;
  17 +
  18 +/**
  19 + * MES 外协发料单行 Service 实现类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Service
  24 +@Validated
  25 +public class MesWmOutsourceIssueLineServiceImpl implements MesWmOutsourceIssueLineService {
  26 +
  27 + @Resource
  28 + private MesWmOutsourceIssueLineMapper outsourceIssueLineMapper;
  29 +
  30 + @Resource
  31 + private MesWmOutsourceIssueDetailService outsourceIssueDetailService;
  32 +
  33 + @Override
  34 + public Long createOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO createReqVO) {
  35 + // TODO @AI:校验关联的 issueId;
  36 + // TODO AI校验关联的 itemId;
  37 +
  38 + // 插入
  39 + MesWmOutsourceIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueLineDO.class);
  40 + outsourceIssueLineMapper.insert(line);
  41 + return line.getId();
  42 + }
  43 +
  44 + @Override
  45 + public void updateOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO updateReqVO) {
  46 + // TODO @AI:校验关联的 issueId;
  47 + // TODO AI校验关联的 itemId;
  48 +
  49 + // 校验存在
  50 + validateOutsourceIssueLineExists(updateReqVO.getId());
  51 + // 更新
  52 + MesWmOutsourceIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueLineDO.class);
  53 + outsourceIssueLineMapper.updateById(updateObj);
  54 + }
  55 +
  56 + @Override
  57 + public void deleteOutsourceIssueLine(Long id) {
  58 + // 校验存在
  59 + validateOutsourceIssueLineExists(id);
  60 + // 级联删除明细
  61 + outsourceIssueDetailService.deleteOutsourceIssueDetailByLineId(id);
  62 + // 删除行
  63 + outsourceIssueLineMapper.deleteById(id);
  64 + }
  65 +
  66 + @Override
  67 + public MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id) {
  68 + return outsourceIssueLineMapper.selectById(id);
  69 + }
  70 +
  71 + @Override
  72 + public PageResult<MesWmOutsourceIssueLineDO> getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO) {
  73 + return outsourceIssueLineMapper.selectPage(pageReqVO);
  74 + }
  75 +
  76 + @Override
  77 + public List<MesWmOutsourceIssueLineDO> getOutsourceIssueLineListByIssueId(Long issueId) {
  78 + return outsourceIssueLineMapper.selectListByIssueId(issueId);
  79 + }
  80 +
  81 + @Override
  82 + public void deleteOutsourceIssueLineByIssueId(Long issueId) {
  83 + outsourceIssueLineMapper.deleteByIssueId(issueId);
  84 + }
  85 +
  86 + private void validateOutsourceIssueLineExists(Long id) {
  87 + if (outsourceIssueLineMapper.selectById(id) == null) {
  88 + throw exception(WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS);
  89 + }
  90 + }
  91 +
  92 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +/**
  10 + * MES 外协发料单 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesWmOutsourceIssueService {
  15 +
  16 + /**
  17 + * 创建外协发料单
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 修改外协发料单
  26 + *
  27 + * @param updateReqVO 修改信息
  28 + */
  29 + void updateOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除外协发料单(级联删除行和明细)
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deleteOutsourceIssue(Long id);
  37 +
  38 + /**
  39 + * 获得外协发料单
  40 + *
  41 + * @param id 编号
  42 + * @return 外协发料单
  43 + */
  44 + MesWmOutsourceIssueDO getOutsourceIssue(Long id);
  45 +
  46 + /**
  47 + * 获得外协发料单分页
  48 + *
  49 + * @param pageReqVO 分页参数
  50 + * @return 外协发料单分页
  51 + */
  52 + PageResult<MesWmOutsourceIssueDO> getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO);
  53 +
  54 + /**
  55 + * 执行外协发料出库(草稿 → 已完成,扣减库存)
  56 + *
  57 + * @param id 编号
  58 + */
  59 + void executeOutsourceIssue(Long id);
  60 +
  61 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO;
  8 +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO;
  10 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO;
  12 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueMapper;
  13 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum;
  14 +import jakarta.annotation.Resource;
  15 +import lombok.extern.slf4j.Slf4j;
  16 +import org.springframework.stereotype.Service;
  17 +import org.springframework.transaction.annotation.Transactional;
  18 +import org.springframework.validation.annotation.Validated;
  19 +
  20 +import java.math.BigDecimal;
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +import java.util.stream.Collectors;
  24 +
  25 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  26 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  27 +
  28 +/**
  29 + * MES 外协发料单 Service 实现类
  30 + *
  31 + * @author 芋道源码
  32 + */
  33 +@Service
  34 +@Validated
  35 +@Slf4j
  36 +public class MesWmOutsourceIssueServiceImpl implements MesWmOutsourceIssueService {
  37 +
  38 + @Resource
  39 + private MesWmOutsourceIssueMapper outsourceIssueMapper;
  40 +
  41 + @Resource
  42 + private MesWmOutsourceIssueLineService outsourceIssueLineService;
  43 +
  44 + @Resource
  45 + private MesWmOutsourceIssueDetailService outsourceIssueDetailService;
  46 +
  47 + @Override
  48 + public Long createOutsourceIssue(MesWmOutsourceIssueSaveReqVO createReqVO) {
  49 + // 校验编码唯一
  50 + validateCodeUnique(null, createReqVO.getCode());
  51 + // TODO @AI:vendorId 非空时,校验供应商存在;
  52 + // TODO @AI:workorderId 无需判断空,需要校验工单存在;
  53 +
  54 + // 插入
  55 + MesWmOutsourceIssueDO issue = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDO.class);
  56 + issue.setStatus(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus());
  57 + outsourceIssueMapper.insert(issue);
  58 + return issue.getId();
  59 + }
  60 +
  61 + @Override
  62 + public void updateOutsourceIssue(MesWmOutsourceIssueSaveReqVO updateReqVO) {
  63 + // 校验存在 + 草稿状态
  64 + validateOutsourceIssueExistsAndDraft(updateReqVO.getId());
  65 + // 校验编码唯一
  66 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
  67 + // TODO @AI:vendorId 非空时,校验供应商存在;
  68 + // TODO @AI:workorderId 无需判断空,需要校验工单存在;
  69 +
  70 + // 更新
  71 + MesWmOutsourceIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDO.class);
  72 + outsourceIssueMapper.updateById(updateObj);
  73 + }
  74 +
  75 + @Override
  76 + @Transactional(rollbackFor = Exception.class)
  77 + public void deleteOutsourceIssue(Long id) {
  78 + // 校验存在 + 草稿状态
  79 + validateOutsourceIssueExistsAndDraft(id);
  80 +
  81 + // 级联删除行和明细
  82 + outsourceIssueLineService.deleteOutsourceIssueLineByIssueId(id);
  83 + outsourceIssueDetailService.deleteOutsourceIssueDetailByIssueId(id);
  84 + // 删除主表
  85 + outsourceIssueMapper.deleteById(id);
  86 + }
  87 +
  88 + @Override
  89 + public MesWmOutsourceIssueDO getOutsourceIssue(Long id) {
  90 + return outsourceIssueMapper.selectById(id);
  91 + }
  92 +
  93 + @Override
  94 + public PageResult<MesWmOutsourceIssueDO> getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO) {
  95 + return outsourceIssueMapper.selectPage(pageReqVO);
  96 + }
  97 +
  98 + @Override
  99 + @Transactional(rollbackFor = Exception.class)
  100 + public void executeOutsourceIssue(Long id) {
  101 + // 1. 校验存在 + 草稿状态
  102 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExistsAndDraft(id);
  103 +
  104 + // 2. 检查是否有发料行
  105 + List<MesWmOutsourceIssueLineDO> lines = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(id);
  106 + if (CollUtil.isEmpty(lines)) {
  107 + throw exception(WM_OUTSOURCE_ISSUE_NO_LINE);
  108 + }
  109 +
  110 + // 3. 校验数量一致性(行数量 = 明细数量之和)
  111 + validateQuantityMatch(id, lines);
  112 +
  113 + // 4. 扣减库存(遍历明细表,逐条扣减)
  114 + List<MesWmOutsourceIssueDetailDO> details = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(id);
  115 + for (MesWmOutsourceIssueDetailDO detail : details) {
  116 + // TODO: 调用库存服务扣减库存
  117 + // materialStockService.decreaseStock(detail.getMaterialStockId(), detail.getQuantity());
  118 + log.info("[executeOutsourceIssue][发料单({}) 扣减库存 - 库存ID: {}, 数量: {}]",
  119 + id, detail.getMaterialStockId(), detail.getQuantity());
  120 + }
  121 +
  122 + // 5. 更新单据状态为已完成
  123 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO()
  124 + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.FINISHED.getStatus()));
  125 + }
  126 +
  127 + /**
  128 + * 校验外协发料单存在
  129 + */
  130 + private MesWmOutsourceIssueDO validateOutsourceIssueExists(Long id) {
  131 + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectById(id);
  132 + if (issue == null) {
  133 + throw exception(WM_OUTSOURCE_ISSUE_NOT_EXISTS);
  134 + }
  135 + return issue;
  136 + }
  137 +
  138 + /**
  139 + * 校验外协发料单存在且为草稿状态
  140 + */
  141 + private MesWmOutsourceIssueDO validateOutsourceIssueExistsAndDraft(Long id) {
  142 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id);
  143 + if (ObjUtil.notEqual(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) {
  144 + throw exception(WM_OUTSOURCE_ISSUE_STATUS_NOT_PREPARE);
  145 + }
  146 + return issue;
  147 + }
  148 +
  149 + /**
  150 + * 校验编码唯一性
  151 + */
  152 + private void validateCodeUnique(Long id, String code) {
  153 + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectByCode(code);
  154 + if (issue == null) {
  155 + return;
  156 + }
  157 + if (ObjUtil.notEqual(id, issue.getId())) {
  158 + throw exception(WM_OUTSOURCE_ISSUE_CODE_DUPLICATE);
  159 + }
  160 + }
  161 +
  162 + /**
  163 + * 校验数量一致性(行数量 = 明细数量之和)
  164 + */
  165 + private void validateQuantityMatch(Long issueId, List<MesWmOutsourceIssueLineDO> lines) {
  166 + // 获取所有明细
  167 + List<MesWmOutsourceIssueDetailDO> details = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(issueId);
  168 +
  169 + // 按行ID分组,计算每行的明细数量之和
  170 + Map<Long, BigDecimal> detailQuantityMap = details.stream()
  171 + .collect(Collectors.groupingBy(
  172 + MesWmOutsourceIssueDetailDO::getLineId,
  173 + Collectors.reducing(BigDecimal.ZERO,
  174 + MesWmOutsourceIssueDetailDO::getQuantity,
  175 + BigDecimal::add)
  176 + ));
  177 +
  178 + // 校验每行的数量是否匹配
  179 + for (MesWmOutsourceIssueLineDO line : lines) {
  180 + BigDecimal detailQuantity = detailQuantityMap.getOrDefault(line.getId(), BigDecimal.ZERO);
  181 + if (line.getQuantity().compareTo(detailQuantity) != 0) {
  182 + log.error("[validateQuantityMatch][发料单({}) 行({}) 数量不匹配 - 行数量: {}, 明细数量: {}]",
  183 + issueId, line.getId(), line.getQuantity(), detailQuantity);
  184 + throw exception(WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH);
  185 + }
  186 + }
  187 + }
  188 +
  189 +}
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
@@ -29,6 +29,7 @@ public interface AuthConvert { @@ -29,6 +29,7 @@ public interface AuthConvert {
29 29
30 AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); 30 AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class);
31 31
  32 +
32 default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) { 33 default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
33 return AuthPermissionInfoRespVO.builder() 34 return AuthPermissionInfoRespVO.builder()
34 .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) 35 .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class))
@@ -85,4 +86,5 @@ public interface AuthConvert { @@ -85,4 +86,5 @@ public interface AuthConvert {
85 86
86 SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp); 87 SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp);
87 88
  89 +
88 } 90 }