diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java index 0116322..03c5870 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; @@ -73,4 +75,12 @@ public class MesWmMiscReceiptLineController { return success(BeanUtils.toBean(list, MesWmMiscReceiptLineRespVO.class)); } + @GetMapping("/page") + @Operation(summary = "获得杂项入库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult> getMiscReceiptLinePage(@Valid MesWmMiscReceiptLinePageReqVO pageReqVO) { + PageResult pageResult = miscReceiptLineService.getMiscReceiptLinePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmMiscReceiptLineRespVO.class)); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java index 3af716b..7c76c4c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -24,7 +25,7 @@ public class MesWmMiscReceiptLineSaveReqVO { @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") @NotNull(message = "入库数量不能为空") - // TODO @AI:最小是 0.01 + @DecimalMin(value = "0.01", message = "入库数量不能小于 0.01") private BigDecimal quantity; @Schema(description = "批次号", example = "BATCH20260301") diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java new file mode 100644 index 0000000..8f227ae --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 杂项入库明细 DO + */ +@TableName("mes_wm_misc_receipt_detail") +@KeySequence("mes_wm_misc_receipt_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscReceiptDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单ID + * + * 关联 {@link MesWmMiscReceiptDO#getId()} + */ + private Long receiptId; + /** + * 行ID + * + * 关联 {@link MesWmMiscReceiptLineDO#getId()} + */ + private Long lineId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 生产日期 + */ + private LocalDateTime productionDate; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 生产批号 + */ + private String productionBatchNumber; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java new file mode 100644 index 0000000..b43da8a --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * MES 外协发料单 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_outsource_issue") +@KeySequence("mes_wm_outsource_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueDO extends BaseDO { + + /** + * 发料单ID + */ + @TableId + private Long id; + /** + * 发料单编号 + */ + private String code; + /** + * 发料单名称 + */ + private String name; + /** + * 供应商ID + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + // TODO @AI:去掉冗余的 vendorCode、vendorName 字段 + /** + * 供应商编码 + */ + private String vendorCode; + /** + * 供应商名称 + */ + private String vendorName; + // TODO @AI:去掉冗余的 workorderCode、workorderName 字段 + // TODO @AI:拼写不对;应该是 workOrderId; + /** + * 生产工单ID + */ + private Long workorderId; + /** + * 生产工单编码 + */ + private String workorderCode; + /** + * 生产工单名称 + */ + private String workorderName; + /** + * 发料日期 + */ + private LocalDateTime issueDate; + /** + * 单据状态 + * + * 枚举 {@link MesWmOutsourceIssueStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java new file mode 100644 index 0000000..14c1de6 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 外协发料单明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_outsource_issue_detail") +@KeySequence("mes_wm_outsource_issue_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueDetailDO extends BaseDO { + + /** + * 明细ID + */ + @TableId + private Long id; + /** + * 行ID + * + * 关联 {@link MesWmOutsourceIssueLineDO#getId()} + */ + private Long lineId; + /** + * 发料单ID + * + * 关联 {@link MesWmOutsourceIssueDO#getId()} + */ + private Long issueId; + /** + * 库存ID + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库位ID + */ + private Long locationId; + /** + * 库区ID + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java new file mode 100644 index 0000000..b8717b7 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 外协发料单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_outsource_issue_line") +@KeySequence("mes_wm_outsource_issue_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueLineDO extends BaseDO { + + /** + * 行ID + */ + @TableId + private Long id; + /** + * 发料单ID + * + * 关联 {@link MesWmOutsourceIssueDO#getId()} + */ + private Long issueId; + /** + * 库存ID + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 发料数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java new file mode 100644 index 0000000..f02cfe0 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项入库明细 Mapper + */ +@Mapper +public interface MesWmMiscReceiptDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmMiscReceiptDetailDO::getLineId, lineId); + } + + default List selectListByReceiptId(Long receiptId) { + return selectList(MesWmMiscReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByReceiptId(Long receiptId) { + delete(MesWmMiscReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmMiscReceiptDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java index 9432645..88994e9 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; import org.apache.ibatis.annotations.Mapper; @@ -26,4 +28,10 @@ public interface MesWmMiscReceiptLineMapper extends BaseMapperX selectPage(MesWmMiscReceiptLinePageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(MesWmMiscReceiptLineDO::getReceiptId, pageReqVO.getReceiptId()) + .orderByAsc(MesWmMiscReceiptLineDO::getId)); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java new file mode 100644 index 0000000..ed28a3c --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协发料单明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueDetailMapper extends BaseMapperX { + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmOutsourceIssueDetailDO::getIssueId, issueId); + } + + default List selectListByLineId(Long lineId) { + return selectList(MesWmOutsourceIssueDetailDO::getLineId, lineId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmOutsourceIssueDetailDO::getIssueId, issueId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmOutsourceIssueDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java new file mode 100644 index 0000000..31e0b2e --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协发料单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceIssueLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmOutsourceIssueLineDO::getIssueId, reqVO.getIssueId()) + .orderByDesc(MesWmOutsourceIssueLineDO::getId)); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmOutsourceIssueLineDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmOutsourceIssueLineDO::getIssueId, issueId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java new file mode 100644 index 0000000..37591c3 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 外协发料单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmOutsourceIssueDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmOutsourceIssueDO::getName, reqVO.getName()) + .eqIfPresent(MesWmOutsourceIssueDO::getVendorId, reqVO.getVendorId()) + .eqIfPresent(MesWmOutsourceIssueDO::getWorkorderId, reqVO.getWorkorderId()) + .likeIfPresent(MesWmOutsourceIssueDO::getWorkorderCode, reqVO.getWorkorderCode()) + .betweenIfPresent(MesWmOutsourceIssueDO::getIssueDate, reqVO.getIssueDate()) + .eqIfPresent(MesWmOutsourceIssueDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesWmOutsourceIssueDO::getId)); + } + + default MesWmOutsourceIssueDO selectByCode(String code) { + return selectOne(MesWmOutsourceIssueDO::getCode, code); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index f137960..10e383c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -466,6 +466,18 @@ public interface ErrorCodeConstants { ErrorCode WM_MISC_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_715_100, "杂项出库单行不存在"); ErrorCode WM_MISC_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_715_200, "杂项出库单明细不存在"); + // ========== MES 仓库管理-杂项入库单(1-040-716-000) ========== + ErrorCode WM_MISC_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_716_000, "杂项入库单不存在"); + ErrorCode WM_MISC_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_716_001, "杂项入库单编码已存在"); + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_716_002, "只有草稿状态才允许此操作"); + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_APPROVED = new ErrorCode(1_040_716_003, "只有已审批状态才允许执行入库"); + ErrorCode WM_MISC_RECEIPT_NO_LINE = new ErrorCode(1_040_716_004, "至少需要一条行项目"); + ErrorCode WM_MISC_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_716_005, "已完成或已取消的入库单不允许取消"); + ErrorCode WM_MISC_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_716_100, "杂项入库单行不存在"); + ErrorCode WM_MISC_RECEIPT_WAREHOUSE_REQUIRED = new ErrorCode(1_040_716_101, "仓库不能为空"); + ErrorCode WM_MISC_RECEIPT_QUANTITY_INVALID = new ErrorCode(1_040_716_102, "入库数量必须大于 0"); + ErrorCode WM_MISC_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_716_200, "杂项入库单明细不存在"); + // ========== MES 仓库管理-发货通知单(1-040-720-000) ========== ErrorCode WM_SALES_NOTICE_NOT_EXISTS = new ErrorCode(1_040_720_000, "发货通知单不存在"); ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java new file mode 100644 index 0000000..ca5edd7 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 外协发料单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmOutsourceIssueStatusEnum implements ArrayValuable { + + /** + * 草稿 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + // TODO @AI:状态缺失了; + /** + * 已完成 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceIssueStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java new file mode 100644 index 0000000..d65ccec --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 委外收货单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmOutsourceReceiptStatusEnum implements ArrayValuable { + + // 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 里的逻辑; + /** + * 准备中 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "准备中"), + /** + * 审批中 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "审批中"), + /** + * 已审批 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "已审批"), + /** + * 已完成 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceReceiptStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java new file mode 100644 index 0000000..0a44355 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; + +/** + * MES 杂项入库明细 Service 接口 + */ +public interface MesWmMiscReceiptDetailService { + + /** + * 创建杂项入库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO); + + /** + * 更新杂项入库明细 + * + * @param updateReqVO 更新信息 + */ + void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO); + + /** + * 删除杂项入库明细(根据入库单ID) + * + * @param receiptId 入库单ID + */ + void deleteMiscReceiptDetailByReceiptId(Long receiptId); + + /** + * 删除杂项入库明细(根据行ID) + * + * @param lineId 行ID + */ + void deleteMiscReceiptDetailByLineId(Long lineId); + + /** + * 校验杂项入库明细是否存在 + * + * @param id 编号 + */ + void validateMiscReceiptDetailExists(Long id); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java new file mode 100644 index 0000000..9676ec0 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_RECEIPT_DETAIL_NOT_EXISTS; + +/** + * MES 杂项入库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmMiscReceiptDetailServiceImpl implements MesWmMiscReceiptDetailService { + + @Resource + private MesWmMiscReceiptDetailMapper receiptDetailMapper; + + @Override + public Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO) { + MesWmMiscReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmMiscReceiptDetailDO.class); + detail.setId(null); // 清空 id,让数据库自动生成 + detail.setLineId(createReqVO.getId()); // VO 的 id 就是 lineId + receiptDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO) { + // 基于 lineId 查询唯一的 detail 记录(VO 的 id 字段是 lineId) + List details = receiptDetailMapper.selectListByLineId(updateReqVO.getId()); + if (CollUtil.isEmpty(details)) { + return; + } + + // 更新 detail(应该只有一条记录) + MesWmMiscReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptDetailDO.class); + updateObj.setId(details.get(0).getId()); // 使用查询到的 detail id + updateObj.setLineId(updateReqVO.getId()); // VO 的 id 就是 lineId + receiptDetailMapper.updateById(updateObj); + } + + @Override + public void deleteMiscReceiptDetailByReceiptId(Long receiptId) { + receiptDetailMapper.deleteByReceiptId(receiptId); + } + + @Override + public void deleteMiscReceiptDetailByLineId(Long lineId) { + receiptDetailMapper.deleteByLineId(lineId); + } + + @Override + public void validateMiscReceiptDetailExists(Long id) { + if (receiptDetailMapper.selectById(id) == null) { + throw exception(WM_MISC_RECEIPT_DETAIL_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java index b9b0452..2ce79b6 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; import jakarta.validation.Valid; @@ -50,6 +52,14 @@ public interface MesWmMiscReceiptLineService { List getMiscReceiptLineListByReceiptId(Long receiptId); /** + * 获得杂项入库单行分页 + * + * @param pageReqVO 分页参数 + * @return 杂项入库单行分页 + */ + PageResult getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO); + + /** * 校验杂项入库单行存在 * * @param id 编号 diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java index 1f9850c..68b8b24 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java @@ -1,11 +1,17 @@ package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; @@ -23,36 +29,69 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ @Resource private MesWmMiscReceiptLineMapper miscReceiptLineMapper; + @Resource + @Lazy + private MesWmMiscReceiptService miscReceiptService; + @Resource + @Lazy + private MesWmMiscReceiptDetailService miscReceiptDetailService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Override + @Transactional(rollbackFor = Exception.class) public Long createMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO createReqVO) { - // TODO @AI:物料存在;lineId 可编辑; + // 1.1 校验父单据存在且为可编辑状态 + miscReceiptService.validateMiscReceiptEditable(createReqVO.getReceiptId()); + // 1.2 校验物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + // 1.3 校验仓库、库区、库位的父子关系 + warehouseAreaService.validateWarehouseAreaExists(createReqVO.getWarehouseId(), + createReqVO.getLocationId(), createReqVO.getAreaId()); - // 插入 + // 2. 新增行 MesWmMiscReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscReceiptLineDO.class); miscReceiptLineMapper.insert(line); - // TODO @AI:还是需要新增一个 detail 表;类似别的 line + detail 的设计;1)create 时,新增;2)update 时,更新;3)delete 时,删除; + + // 3. 自动创建明细 + createReqVO.setId(line.getId()); + miscReceiptDetailService.createMiscReceiptDetail(createReqVO); return line.getId(); } @Override + @Transactional(rollbackFor = Exception.class) public void updateMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO updateReqVO) { - // 校验存在 - validateMiscReceiptLineExists(updateReqVO.getId()); - // TODO @AI:物料存在;lineId 可编辑; + // 1.1 校验存在 + MesWmMiscReceiptLineDO line = validateMiscReceiptLineExists(updateReqVO.getId()); + // 1.2 校验父单据存在且为可编辑状态 + miscReceiptService.validateMiscReceiptEditable(line.getReceiptId()); + // 1.3 校验物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + // 1.4 校验仓库、库区、库位的父子关系 + warehouseAreaService.validateWarehouseAreaExists(updateReqVO.getWarehouseId(), + updateReqVO.getLocationId(), updateReqVO.getAreaId()); - // 更新 + // 2. 更新行 MesWmMiscReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptLineDO.class); miscReceiptLineMapper.updateById(updateObj); + + // 3. 更新明细(基于行信息) + miscReceiptDetailService.updateMiscReceiptDetail(updateReqVO); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteMiscReceiptLine(Long id) { - // TODO @AI:lineId 存在 + 可编辑; // 校验存在 validateMiscReceiptLineExists(id); - // 删除 + // 删除行 miscReceiptLineMapper.deleteById(id); + // 删除明细 + miscReceiptDetailService.deleteMiscReceiptDetailByLineId(id); } @Override @@ -66,6 +105,11 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ } @Override + public PageResult getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO) { + return miscReceiptLineMapper.selectPage(pageReqVO); + } + + @Override public MesWmMiscReceiptLineDO validateMiscReceiptLineExists(Long id) { MesWmMiscReceiptLineDO line = miscReceiptLineMapper.selectById(id); if (line == null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java index 2ad8a29..08e607f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java @@ -80,4 +80,11 @@ public interface MesWmMiscReceiptService { */ MesWmMiscReceiptDO validateMiscReceiptExists(Long id); + /** + * 校验杂项入库单是否可编辑(存在且为草稿状态) + * + * @param id 编号 + */ + void validateMiscReceiptEditable(Long id); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java index bf4fcd0..f52b1a5 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java +++ b/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 { private MesWmMiscReceiptLineMapper miscReceiptLineMapper; @Resource + private MesWmMiscReceiptDetailService miscReceiptDetailService; + + @Resource private MesWmMaterialStockService materialStockService; @Override @@ -70,6 +73,8 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { // 校验存在 + 草稿状态 validateMiscReceiptExistsAndPrepare(id); + // 级联删除明细 + miscReceiptDetailService.deleteMiscReceiptDetailByReceiptId(id); // 级联删除行 miscReceiptLineMapper.deleteByReceiptId(id); // 删除主表 @@ -158,8 +163,6 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { return receipt; } - // ==================== 私有方法 ==================== - private void validateCodeUnique(Long id, String code) { MesWmMiscReceiptDO receipt = miscReceiptMapper.selectByCode(code); if (receipt == null) { @@ -178,4 +181,13 @@ public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { return receipt; } + /** + * 校验入库单是否可编辑(存在且为草稿状态) + * + * @param id 入库单ID + */ + public void validateMiscReceiptEditable(Long id) { + validateMiscReceiptExistsAndPrepare(id); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java new file mode 100644 index 0000000..e7ae9cd --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 外协发料单明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueDetailService { + + /** + * 创建外协发料单明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO createReqVO); + + /** + * 修改外协发料单明细 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO updateReqVO); + + /** + * 删除外协发料单明细 + * + * @param id 编号 + */ + void deleteOutsourceIssueDetail(Long id); + + /** + * 获得外协发料单明细 + * + * @param id 编号 + * @return 外协发料单明细 + */ + MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id); + + /** + * 获得外协发料单明细列表 + * + * @param issueId 发料单ID + * @return 外协发料单明细列表 + */ + List getOutsourceIssueDetailListByIssueId(Long issueId); + + /** + * 获得外协发料单明细列表 + * + * @param lineId 行ID + * @return 外协发料单明细列表 + */ + List getOutsourceIssueDetailListByLineId(Long lineId); + + /** + * 删除外协发料单明细 + * + * @param issueId 发料单ID + */ + void deleteOutsourceIssueDetailByIssueId(Long issueId); + + /** + * 删除外协发料单明细 + * + * @param lineId 行ID + */ + void deleteOutsourceIssueDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java new file mode 100644 index 0000000..88f29a7 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS; + +/** + * MES 外协发料单明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssueDetailService { + + @Resource + private MesWmOutsourceIssueDetailMapper outsourceIssueDetailMapper; + + @Override + public Long createOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO createReqVO) { + // TODO @AI:校验关联的 issueId; + // TODO AI校验关联的 itemId; + + // 插入 + MesWmOutsourceIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDetailDO.class); + outsourceIssueDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO updateReqVO) { + // 校验存在 + validateOutsourceIssueDetailExists(updateReqVO.getId()); + // TODO @AI:校验关联的 issueId; + // TODO AI校验关联的 itemId; + + // 更新 + MesWmOutsourceIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDetailDO.class); + outsourceIssueDetailMapper.updateById(updateObj); + } + + @Override + public void deleteOutsourceIssueDetail(Long id) { + // 校验存在 + validateOutsourceIssueDetailExists(id); + // 删除 + outsourceIssueDetailMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id) { + return outsourceIssueDetailMapper.selectById(id); + } + + @Override + public List getOutsourceIssueDetailListByIssueId(Long issueId) { + return outsourceIssueDetailMapper.selectListByIssueId(issueId); + } + + @Override + public List getOutsourceIssueDetailListByLineId(Long lineId) { + return outsourceIssueDetailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteOutsourceIssueDetailByIssueId(Long issueId) { + outsourceIssueDetailMapper.deleteByIssueId(issueId); + } + + @Override + public void deleteOutsourceIssueDetailByLineId(Long lineId) { + outsourceIssueDetailMapper.deleteByLineId(lineId); + } + + private void validateOutsourceIssueDetailExists(Long id) { + if (outsourceIssueDetailMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java new file mode 100644 index 0000000..ea2f03f --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 外协发料单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueLineService { + + /** + * 创建外协发料单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO createReqVO); + + /** + * 修改外协发料单行 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO updateReqVO); + + /** + * 删除外协发料单行 + * + * @param id 编号 + */ + void deleteOutsourceIssueLine(Long id); + + /** + * 获得外协发料单行 + * + * @param id 编号 + * @return 外协发料单行 + */ + MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id); + + /** + * 获得外协发料单行分页 + * + * @param pageReqVO 分页参数 + * @return 外协发料单行分页 + */ + PageResult getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO); + + /** + * 获得外协发料单行列表 + * + * @param issueId 发料单ID + * @return 外协发料单行列表 + */ + List getOutsourceIssueLineListByIssueId(Long issueId); + + /** + * 删除外协发料单行 + * + * @param issueId 发料单ID + */ + void deleteOutsourceIssueLineByIssueId(Long issueId); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java new file mode 100644 index 0000000..c34c22c --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueLineMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS; + +/** + * MES 外协发料单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmOutsourceIssueLineServiceImpl implements MesWmOutsourceIssueLineService { + + @Resource + private MesWmOutsourceIssueLineMapper outsourceIssueLineMapper; + + @Resource + private MesWmOutsourceIssueDetailService outsourceIssueDetailService; + + @Override + public Long createOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO createReqVO) { + // TODO @AI:校验关联的 issueId; + // TODO AI校验关联的 itemId; + + // 插入 + MesWmOutsourceIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueLineDO.class); + outsourceIssueLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO updateReqVO) { + // TODO @AI:校验关联的 issueId; + // TODO AI校验关联的 itemId; + + // 校验存在 + validateOutsourceIssueLineExists(updateReqVO.getId()); + // 更新 + MesWmOutsourceIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueLineDO.class); + outsourceIssueLineMapper.updateById(updateObj); + } + + @Override + public void deleteOutsourceIssueLine(Long id) { + // 校验存在 + validateOutsourceIssueLineExists(id); + // 级联删除明细 + outsourceIssueDetailService.deleteOutsourceIssueDetailByLineId(id); + // 删除行 + outsourceIssueLineMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id) { + return outsourceIssueLineMapper.selectById(id); + } + + @Override + public PageResult getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO) { + return outsourceIssueLineMapper.selectPage(pageReqVO); + } + + @Override + public List getOutsourceIssueLineListByIssueId(Long issueId) { + return outsourceIssueLineMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteOutsourceIssueLineByIssueId(Long issueId) { + outsourceIssueLineMapper.deleteByIssueId(issueId); + } + + private void validateOutsourceIssueLineExists(Long id) { + if (outsourceIssueLineMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java new file mode 100644 index 0000000..9a1a105 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import jakarta.validation.Valid; + +/** + * MES 外协发料单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueService { + + /** + * 创建外协发料单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO createReqVO); + + /** + * 修改外协发料单 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO updateReqVO); + + /** + * 删除外协发料单(级联删除行和明细) + * + * @param id 编号 + */ + void deleteOutsourceIssue(Long id); + + /** + * 获得外协发料单 + * + * @param id 编号 + * @return 外协发料单 + */ + MesWmOutsourceIssueDO getOutsourceIssue(Long id); + + /** + * 获得外协发料单分页 + * + * @param pageReqVO 分页参数 + * @return 外协发料单分页 + */ + PageResult getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO); + + /** + * 执行外协发料出库(草稿 → 已完成,扣减库存) + * + * @param id 编号 + */ + void executeOutsourceIssue(Long id); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java new file mode 100644 index 0000000..e53fca0 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java @@ -0,0 +1,189 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 外协发料单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class MesWmOutsourceIssueServiceImpl implements MesWmOutsourceIssueService { + + @Resource + private MesWmOutsourceIssueMapper outsourceIssueMapper; + + @Resource + private MesWmOutsourceIssueLineService outsourceIssueLineService; + + @Resource + private MesWmOutsourceIssueDetailService outsourceIssueDetailService; + + @Override + public Long createOutsourceIssue(MesWmOutsourceIssueSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + // TODO @AI:vendorId 非空时,校验供应商存在; + // TODO @AI:workorderId 无需判断空,需要校验工单存在; + + // 插入 + MesWmOutsourceIssueDO issue = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDO.class); + issue.setStatus(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus()); + outsourceIssueMapper.insert(issue); + return issue.getId(); + } + + @Override + public void updateOutsourceIssue(MesWmOutsourceIssueSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateOutsourceIssueExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // TODO @AI:vendorId 非空时,校验供应商存在; + // TODO @AI:workorderId 无需判断空,需要校验工单存在; + + // 更新 + MesWmOutsourceIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDO.class); + outsourceIssueMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteOutsourceIssue(Long id) { + // 校验存在 + 草稿状态 + validateOutsourceIssueExistsAndDraft(id); + + // 级联删除行和明细 + outsourceIssueLineService.deleteOutsourceIssueLineByIssueId(id); + outsourceIssueDetailService.deleteOutsourceIssueDetailByIssueId(id); + // 删除主表 + outsourceIssueMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueDO getOutsourceIssue(Long id) { + return outsourceIssueMapper.selectById(id); + } + + @Override + public PageResult getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO) { + return outsourceIssueMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void executeOutsourceIssue(Long id) { + // 1. 校验存在 + 草稿状态 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExistsAndDraft(id); + + // 2. 检查是否有发料行 + List lines = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_OUTSOURCE_ISSUE_NO_LINE); + } + + // 3. 校验数量一致性(行数量 = 明细数量之和) + validateQuantityMatch(id, lines); + + // 4. 扣减库存(遍历明细表,逐条扣减) + List details = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(id); + for (MesWmOutsourceIssueDetailDO detail : details) { + // TODO: 调用库存服务扣减库存 + // materialStockService.decreaseStock(detail.getMaterialStockId(), detail.getQuantity()); + log.info("[executeOutsourceIssue][发料单({}) 扣减库存 - 库存ID: {}, 数量: {}]", + id, detail.getMaterialStockId(), detail.getQuantity()); + } + + // 5. 更新单据状态为已完成 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO() + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.FINISHED.getStatus())); + } + + /** + * 校验外协发料单存在 + */ + private MesWmOutsourceIssueDO validateOutsourceIssueExists(Long id) { + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectById(id); + if (issue == null) { + throw exception(WM_OUTSOURCE_ISSUE_NOT_EXISTS); + } + return issue; + } + + /** + * 校验外协发料单存在且为草稿状态 + */ + private MesWmOutsourceIssueDO validateOutsourceIssueExistsAndDraft(Long id) { + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id); + if (ObjUtil.notEqual(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { + throw exception(WM_OUTSOURCE_ISSUE_STATUS_NOT_PREPARE); + } + return issue; + } + + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_OUTSOURCE_ISSUE_CODE_DUPLICATE); + } + } + + /** + * 校验数量一致性(行数量 = 明细数量之和) + */ + private void validateQuantityMatch(Long issueId, List lines) { + // 获取所有明细 + List details = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(issueId); + + // 按行ID分组,计算每行的明细数量之和 + Map detailQuantityMap = details.stream() + .collect(Collectors.groupingBy( + MesWmOutsourceIssueDetailDO::getLineId, + Collectors.reducing(BigDecimal.ZERO, + MesWmOutsourceIssueDetailDO::getQuantity, + BigDecimal::add) + )); + + // 校验每行的数量是否匹配 + for (MesWmOutsourceIssueLineDO line : lines) { + BigDecimal detailQuantity = detailQuantityMap.getOrDefault(line.getId(), BigDecimal.ZERO); + if (line.getQuantity().compareTo(detailQuantity) != 0) { + log.error("[validateQuantityMatch][发料单({}) 行({}) 数量不匹配 - 行数量: {}, 明细数量: {}]", + issueId, line.getId(), line.getQuantity(), detailQuantity); + throw exception(WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH); + } + } + } + +} diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index b896275..b03043a 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -29,6 +29,7 @@ public interface AuthConvert { AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); + default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) @@ -85,4 +86,5 @@ public interface AuthConvert { SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp); + }