Commit c5407a6f9f85bd8a456add8740d80096d5022edf

Authored by YunaiV
1 parent ef7b2ab4

✨ feat(mes): 添加杂项出库单及行相关功能

新增杂项出库单及行的请求和响应对象,更新相关的接口和枚举,支持杂项出库单的创建、修改、删除和查询功能。优化了相关的业务逻辑和数据结构,以提升系统的可维护性和扩展性。
Showing 18 changed files with 1242 additions and 5 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
  5 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  9 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO;
  11 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueRespVO;
  12 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO;
  14 +import cn.iocoder.yudao.module.mes.service.wm.miscissue.MesWmMiscIssueService;
  15 +import io.swagger.v3.oas.annotations.Operation;
  16 +import io.swagger.v3.oas.annotations.Parameter;
  17 +import io.swagger.v3.oas.annotations.tags.Tag;
  18 +import jakarta.annotation.Resource;
  19 +import jakarta.servlet.http.HttpServletResponse;
  20 +import jakarta.validation.Valid;
  21 +import org.springframework.security.access.prepost.PreAuthorize;
  22 +import org.springframework.validation.annotation.Validated;
  23 +import org.springframework.web.bind.annotation.*;
  24 +
  25 +import java.io.IOException;
  26 +import java.util.Collections;
  27 +import java.util.List;
  28 +
  29 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  30 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  31 +
  32 +@Tag(name = "管理后台 - MES 杂项出库单")
  33 +@RestController
  34 +@RequestMapping("/mes/wm/misc-issue")
  35 +@Validated
  36 +public class MesWmMiscIssueController {
  37 +
  38 + @Resource
  39 + private MesWmMiscIssueService miscIssueService;
  40 +
  41 + @PostMapping("/create")
  42 + @Operation(summary = "创建杂项出库单")
  43 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:create')")
  44 + public CommonResult<Long> createMiscIssue(@Valid @RequestBody MesWmMiscIssueSaveReqVO createReqVO) {
  45 + return success(miscIssueService.createMiscIssue(createReqVO));
  46 + }
  47 +
  48 + @PutMapping("/update")
  49 + @Operation(summary = "修改杂项出库单")
  50 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')")
  51 + public CommonResult<Boolean> updateMiscIssue(@Valid @RequestBody MesWmMiscIssueSaveReqVO updateReqVO) {
  52 + miscIssueService.updateMiscIssue(updateReqVO);
  53 + return success(true);
  54 + }
  55 +
  56 + @DeleteMapping("/delete")
  57 + @Operation(summary = "删除杂项出库单")
  58 + @Parameter(name = "id", description = "编号", required = true)
  59 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:delete')")
  60 + public CommonResult<Boolean> deleteMiscIssue(@RequestParam("id") Long id) {
  61 + miscIssueService.deleteMiscIssue(id);
  62 + return success(true);
  63 + }
  64 +
  65 + @GetMapping("/get")
  66 + @Operation(summary = "获得杂项出库单")
  67 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  68 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')")
  69 + public CommonResult<MesWmMiscIssueRespVO> getMiscIssue(@RequestParam("id") Long id) {
  70 + MesWmMiscIssueDO issue = miscIssueService.getMiscIssue(id);
  71 + if (issue == null) {
  72 + return success(null);
  73 + }
  74 + return success(buildRespVOList(Collections.singletonList(issue)).get(0));
  75 + }
  76 +
  77 + @GetMapping("/page")
  78 + @Operation(summary = "获得杂项出库单分页")
  79 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')")
  80 + public CommonResult<PageResult<MesWmMiscIssueRespVO>> getMiscIssuePage(
  81 + @Valid MesWmMiscIssuePageReqVO pageReqVO) {
  82 + PageResult<MesWmMiscIssueDO> pageResult = miscIssueService.getMiscIssuePage(pageReqVO);
  83 + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
  84 + }
  85 +
  86 + @GetMapping("/export-excel")
  87 + @Operation(summary = "导出杂项出库单 Excel")
  88 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:export')")
  89 + @ApiAccessLog(operateType = EXPORT)
  90 + public void exportMiscIssueExcel(@Valid MesWmMiscIssuePageReqVO pageReqVO,
  91 + HttpServletResponse response) throws IOException {
  92 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  93 + PageResult<MesWmMiscIssueDO> pageResult = miscIssueService.getMiscIssuePage(pageReqVO);
  94 + ExcelUtils.write(response, "杂项出库单.xls", "数据", MesWmMiscIssueRespVO.class,
  95 + buildRespVOList(pageResult.getList()));
  96 + }
  97 +
  98 + @PutMapping("/submit")
  99 + @Operation(summary = "提交杂项出库单")
  100 + @Parameter(name = "id", description = "编号", required = true)
  101 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')")
  102 + public CommonResult<Boolean> submitMiscIssue(@RequestParam("id") Long id) {
  103 + miscIssueService.submitMiscIssue(id);
  104 + return success(true);
  105 + }
  106 +
  107 + @PutMapping("/finish")
  108 + @Operation(summary = "执行出库")
  109 + @Parameter(name = "id", description = "编号", required = true)
  110 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:finish')")
  111 + public CommonResult<Boolean> finishMiscIssue(@RequestParam("id") Long id) {
  112 + miscIssueService.finishMiscIssue(id);
  113 + return success(true);
  114 + }
  115 +
  116 + @PutMapping("/cancel")
  117 + @Operation(summary = "取消杂项出库单")
  118 + @Parameter(name = "id", description = "编号", required = true)
  119 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')")
  120 + public CommonResult<Boolean> cancelMiscIssue(@RequestParam("id") Long id) {
  121 + miscIssueService.cancelMiscIssue(id);
  122 + return success(true);
  123 + }
  124 +
  125 + // ==================== 拼接 VO ====================
  126 +
  127 + private List<MesWmMiscIssueRespVO> buildRespVOList(List<MesWmMiscIssueDO> list) {
  128 + if (CollUtil.isEmpty(list)) {
  129 + return Collections.emptyList();
  130 + }
  131 + return BeanUtils.toBean(list, MesWmMiscIssueRespVO.class);
  132 + }
  133 +
  134 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  8 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineRespVO;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
  14 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  15 +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
  16 +import cn.iocoder.yudao.module.mes.service.wm.miscissue.MesWmMiscIssueLineService;
  17 +import io.swagger.v3.oas.annotations.Operation;
  18 +import io.swagger.v3.oas.annotations.Parameter;
  19 +import io.swagger.v3.oas.annotations.tags.Tag;
  20 +import jakarta.annotation.Resource;
  21 +import jakarta.validation.Valid;
  22 +import org.springframework.security.access.prepost.PreAuthorize;
  23 +import org.springframework.validation.annotation.Validated;
  24 +import org.springframework.web.bind.annotation.*;
  25 +
  26 +import java.util.Collections;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +
  30 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  31 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  32 +
  33 +@Tag(name = "管理后台 - MES 杂项出库单行")
  34 +@RestController
  35 +@RequestMapping("/mes/wm/misc-issue-line")
  36 +@Validated
  37 +public class MesWmMiscIssueLineController {
  38 +
  39 + @Resource
  40 + private MesWmMiscIssueLineService miscIssueLineService;
  41 +
  42 + @Resource
  43 + private MesMdItemService itemService;
  44 +
  45 + @Resource
  46 + private MesMdUnitMeasureService unitMeasureService;
  47 +
  48 + @PostMapping("/create")
  49 + @Operation(summary = "创建杂项出库单行")
  50 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:create')")
  51 + public CommonResult<Long> createMiscIssueLine(@Valid @RequestBody MesWmMiscIssueLineSaveReqVO createReqVO) {
  52 + return success(miscIssueLineService.createMiscIssueLine(createReqVO));
  53 + }
  54 +
  55 + @PutMapping("/update")
  56 + @Operation(summary = "修改杂项出库单行")
  57 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')")
  58 + public CommonResult<Boolean> updateMiscIssueLine(@Valid @RequestBody MesWmMiscIssueLineSaveReqVO updateReqVO) {
  59 + miscIssueLineService.updateMiscIssueLine(updateReqVO);
  60 + return success(true);
  61 + }
  62 +
  63 + @DeleteMapping("/delete")
  64 + @Operation(summary = "删除杂项出库单行")
  65 + @Parameter(name = "id", description = "编号", required = true)
  66 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:delete')")
  67 + public CommonResult<Boolean> deleteMiscIssueLine(@RequestParam("id") Long id) {
  68 + miscIssueLineService.deleteMiscIssueLine(id);
  69 + return success(true);
  70 + }
  71 +
  72 + @GetMapping("/get")
  73 + @Operation(summary = "获得杂项出库单行")
  74 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  75 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')")
  76 + public CommonResult<MesWmMiscIssueLineRespVO> getMiscIssueLine(@RequestParam("id") Long id) {
  77 + MesWmMiscIssueLineDO line = miscIssueLineService.getMiscIssueLine(id);
  78 + if (line == null) {
  79 + return success(null);
  80 + }
  81 + return success(buildRespVOList(Collections.singletonList(line)).get(0));
  82 + }
  83 +
  84 + @GetMapping("/page")
  85 + @Operation(summary = "获得杂项出库单行分页")
  86 + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')")
  87 + public CommonResult<PageResult<MesWmMiscIssueLineRespVO>> getMiscIssueLinePage(
  88 + @Valid MesWmMiscIssueLinePageReqVO pageReqVO) {
  89 + PageResult<MesWmMiscIssueLineDO> pageResult = miscIssueLineService.getMiscIssueLinePage(pageReqVO);
  90 + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
  91 + }
  92 +
  93 + // ==================== 拼接 VO ====================
  94 +
  95 + private List<MesWmMiscIssueLineRespVO> buildRespVOList(List<MesWmMiscIssueLineDO> list) {
  96 + if (CollUtil.isEmpty(list)) {
  97 + return Collections.emptyList();
  98 + }
  99 + // 1. 获得关联数据
  100 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
  101 + convertSet(list, MesWmMiscIssueLineDO::getItemId));
  102 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  103 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  104 + // 2. 构建结果
  105 + return BeanUtils.toBean(list, MesWmMiscIssueLineRespVO.class, vo -> {
  106 + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
  107 + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
  108 + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  109 + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
  110 + });
  111 + });
  112 + }
  113 +
  114 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssuePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  12 +
  13 +@Schema(description = "管理后台 - MES 杂项出库单分页 Request VO")
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +public class MesWmMiscIssuePageReqVO extends PageParam {
  17 +
  18 + @Schema(description = "出库单编号", example = "MI20260302001")
  19 + private String code;
  20 +
  21 + @Schema(description = "出库单名称", example = "库存调整出库")
  22 + private String name;
  23 +
  24 + @Schema(description = "杂项类型", example = "STOCK_ADJUSTMENT")
  25 + private String type;
  26 +
  27 + @Schema(description = "状态", example = "0")
  28 + private Integer status;
  29 +
  30 + @Schema(description = "出库日期范围")
  31 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  32 + private LocalDateTime[] issueDate;
  33 +
  34 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +@Schema(description = "管理后台 - MES 杂项出库单 Response VO")
  9 +@Data
  10 +public class MesWmMiscIssueRespVO {
  11 +
  12 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  13 + private Long id;
  14 +
  15 + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MI20260302001")
  16 + private String code;
  17 +
  18 + @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存调整出库")
  19 + private String name;
  20 +
  21 + @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "STOCK_ADJUSTMENT")
  22 + private String type;
  23 +
  24 + @Schema(description = "来源单据ID", example = "1")
  25 + private Long sourceDocId;
  26 +
  27 + @Schema(description = "来源单据编号", example = "DOC20260302001")
  28 + private String sourceDocCode;
  29 +
  30 + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER")
  31 + private String sourceDocType;
  32 +
  33 + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED)
  34 + private LocalDateTime issueDate;
  35 +
  36 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  37 + private Integer status;
  38 +
  39 + @Schema(description = "备注", example = "备注")
  40 + private String remark;
  41 +
  42 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  43 + private LocalDateTime createTime;
  44 +
  45 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotBlank;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - MES 杂项出库单新增/修改 Request VO")
  11 +@Data
  12 +public class MesWmMiscIssueSaveReqVO {
  13 +
  14 + @Schema(description = "编号", example = "1024")
  15 + private Long id;
  16 +
  17 + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MI20260302001")
  18 + @NotBlank(message = "出库单编号不能为空")
  19 + private String code;
  20 +
  21 + @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存调整出库")
  22 + @NotBlank(message = "出库单名称不能为空")
  23 + private String name;
  24 +
  25 + @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "STOCK_ADJUSTMENT")
  26 + @NotBlank(message = "杂项类型不能为空")
  27 + private String type;
  28 +
  29 + @Schema(description = "来源单据ID", example = "1")
  30 + private Long sourceDocId;
  31 +
  32 + @Schema(description = "来源单据编号", example = "DOC20260302001")
  33 + private String sourceDocCode;
  34 +
  35 + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER")
  36 + private String sourceDocType;
  37 +
  38 + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED)
  39 + @NotNull(message = "出库日期不能为空")
  40 + private LocalDateTime issueDate;
  41 +
  42 + @Schema(description = "备注", example = "备注")
  43 + private String remark;
  44 +
  45 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLinePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +@Schema(description = "管理后台 - MES 杂项出库单行分页 Request VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class MesWmMiscIssueLinePageReqVO extends PageParam {
  15 +
  16 + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotNull(message = "出库单编号不能为空")
  18 + private Long issueId;
  19 +
  20 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.math.BigDecimal;
  7 +import java.time.LocalDateTime;
  8 +
  9 +@Schema(description = "管理后台 - MES 杂项出库单行 Response VO")
  10 +@Data
  11 +public class MesWmMiscIssueLineRespVO {
  12 +
  13 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  14 + private Long id;
  15 +
  16 + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + private Long issueId;
  18 +
  19 + @Schema(description = "来源单据行ID", example = "1")
  20 + private Long sourceDocLineId;
  21 +
  22 + @Schema(description = "库存记录ID", example = "1")
  23 + private Long materialStockId;
  24 +
  25 + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  26 + private Long itemId;
  27 +
  28 + @Schema(description = "物料编码", example = "M001")
  29 + private String itemCode;
  30 +
  31 + @Schema(description = "物料名称", example = "钢板")
  32 + private String itemName;
  33 +
  34 + @Schema(description = "规格型号", example = "10mm*100mm")
  35 + private String specification;
  36 +
  37 + @Schema(description = "计量单位名称", example = "千克")
  38 + private String unitMeasureName;
  39 +
  40 + @Schema(description = "出库数量", example = "100.00")
  41 + private BigDecimal quantity;
  42 +
  43 + @Schema(description = "批次编号", example = "1")
  44 + private Long batchId;
  45 +
  46 + @Schema(description = "仓库编号", example = "1")
  47 + private Long warehouseId;
  48 +
  49 + @Schema(description = "库区编号", example = "1")
  50 + private Long locationId;
  51 +
  52 + @Schema(description = "库位编号", example = "1")
  53 + private Long areaId;
  54 +
  55 + @Schema(description = "备注", example = "备注")
  56 + private String remark;
  57 +
  58 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  59 + private LocalDateTime createTime;
  60 +
  61 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.DecimalMin;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +import java.math.BigDecimal;
  9 +
  10 +@Schema(description = "管理后台 - MES 杂项出库单行新增/修改 Request VO")
  11 +@Data
  12 +public class MesWmMiscIssueLineSaveReqVO {
  13 +
  14 + @Schema(description = "编号", example = "1024")
  15 + private Long id;
  16 +
  17 + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  18 + @NotNull(message = "出库单编号不能为空")
  19 + private Long issueId;
  20 +
  21 + @Schema(description = "来源单据行ID", example = "1")
  22 + private Long sourceDocLineId;
  23 +
  24 + @Schema(description = "库存记录ID", example = "1")
  25 + private Long materialStockId;
  26 +
  27 + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  28 + @NotNull(message = "物料编号不能为空")
  29 + private Long itemId;
  30 +
  31 + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
  32 + @NotNull(message = "出库数量不能为空")
  33 + @DecimalMin(value = "0.01", message = "出库数量必须大于0")
  34 + private BigDecimal quantity;
  35 +
  36 + @Schema(description = "批次编号", example = "1")
  37 + private Long batchId;
  38 +
  39 + @Schema(description = "仓库编号", example = "1")
  40 + private Long warehouseId;
  41 +
  42 + @Schema(description = "库区编号", example = "1")
  43 + private Long locationId;
  44 +
  45 + @Schema(description = "库位编号", example = "1")
  46 + private Long areaId;
  47 +
  48 + @Schema(description = "备注", example = "备注")
  49 + private String remark;
  50 +
  51 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueStatusEnum;
  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.time.LocalDateTime;
  11 +
  12 +/**
  13 + * MES 杂项出库单 DO
  14 + */
  15 +@TableName("mes_wm_misc_issue")
  16 +@KeySequence("mes_wm_misc_issue_seq")
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class MesWmMiscIssueDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 出库单编号
  32 + */
  33 + private String code;
  34 + /**
  35 + * 出库单名称
  36 + */
  37 + private String name;
  38 + // TODO @AI:字典;需要写在 dict constants 里;
  39 + /**
  40 + * 杂项类型
  41 + */
  42 + private String type;
  43 + // TODO @芋艿:这里还没定,关联哪些;
  44 + /**
  45 + * 来源单据ID
  46 + */
  47 + private Long sourceDocId;
  48 + /**
  49 + * 来源单据编号
  50 + */
  51 + private String sourceDocCode;
  52 + /**
  53 + * 来源单据类型
  54 + */
  55 + private String sourceDocType;
  56 + /**
  57 + * 出库日期
  58 + */
  59 + private LocalDateTime issueDate;
  60 + /**
  61 + * 状态
  62 + *
  63 + * 枚举 {@link MesWmMiscIssueStatusEnum}
  64 + */
  65 + private Integer status;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String remark;
  70 +
  71 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue;
  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 +
  15 +/**
  16 + * MES 杂项出库单行 DO
  17 + */
  18 +@TableName("mes_wm_misc_issue_line")
  19 +@KeySequence("mes_wm_misc_issue_line_seq")
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +@ToString(callSuper = true)
  23 +@Builder
  24 +@NoArgsConstructor
  25 +@AllArgsConstructor
  26 +public class MesWmMiscIssueLineDO extends BaseDO {
  27 +
  28 + /**
  29 + * 编号
  30 + */
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 出库单编号
  35 + *
  36 + * 关联 {@link MesWmMiscIssueDO#getId()}
  37 + */
  38 + private Long issueId;
  39 + /**
  40 + * 来源单据行ID
  41 + */
  42 + private Long sourceDocLineId;
  43 + /**
  44 + * 库存记录ID
  45 + */
  46 + private Long materialStockId;
  47 + /**
  48 + * 物料编号
  49 + *
  50 + * 关联 {@link MesMdItemDO#getId()}
  51 + */
  52 + private Long itemId;
  53 + /**
  54 + * 出库数量
  55 + */
  56 + private BigDecimal quantity;
  57 + /**
  58 + * 批次编号
  59 + */
  60 + private Long batchId;
  61 + /**
  62 + * 仓库编号
  63 + *
  64 + * 关联 {@link MesWmWarehouseDO#getId()}
  65 + */
  66 + private Long warehouseId;
  67 + /**
  68 + * 库区编号
  69 + *
  70 + * 关联 {@link MesWmWarehouseLocationDO#getId()}
  71 + */
  72 + private Long locationId;
  73 + /**
  74 + * 库位编号
  75 + *
  76 + * 关联 {@link MesWmWarehouseAreaDO#getId()}
  77 + */
  78 + private Long areaId;
  79 + /**
  80 + * 备注
  81 + */
  82 + private String remark;
  83 +
  84 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueLineMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue;
  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.miscissue.vo.line.MesWmMiscIssueLinePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * MES 杂项出库单行 Mapper
  14 + */
  15 +@Mapper
  16 +public interface MesWmMiscIssueLineMapper extends BaseMapperX<MesWmMiscIssueLineDO> {
  17 +
  18 + default PageResult<MesWmMiscIssueLineDO> selectPage(MesWmMiscIssueLinePageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmMiscIssueLineDO>()
  20 + .eqIfPresent(MesWmMiscIssueLineDO::getIssueId, reqVO.getIssueId())
  21 + .orderByDesc(MesWmMiscIssueLineDO::getId));
  22 + }
  23 +
  24 + default List<MesWmMiscIssueLineDO> selectListByIssueId(Long issueId) {
  25 + return selectList(MesWmMiscIssueLineDO::getIssueId, issueId);
  26 + }
  27 +
  28 + default void deleteByIssueId(Long issueId) {
  29 + delete(MesWmMiscIssueLineDO::getIssueId, issueId);
  30 + }
  31 +
  32 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue;
  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.miscissue.vo.MesWmMiscIssuePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * MES 杂项出库单 Mapper
  14 + */
  15 +@Mapper
  16 +public interface MesWmMiscIssueMapper extends BaseMapperX<MesWmMiscIssueDO> {
  17 +
  18 + default PageResult<MesWmMiscIssueDO> selectPage(MesWmMiscIssuePageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmMiscIssueDO>()
  20 + .likeIfPresent(MesWmMiscIssueDO::getCode, reqVO.getCode())
  21 + .likeIfPresent(MesWmMiscIssueDO::getName, reqVO.getName())
  22 + .eqIfPresent(MesWmMiscIssueDO::getType, reqVO.getType())
  23 + .eqIfPresent(MesWmMiscIssueDO::getStatus, reqVO.getStatus())
  24 + .betweenIfPresent(MesWmMiscIssueDO::getIssueDate, reqVO.getIssueDate())
  25 + .orderByDesc(MesWmMiscIssueDO::getId));
  26 + }
  27 +
  28 + default MesWmMiscIssueDO selectByCode(String code) {
  29 + return selectOne(MesWmMiscIssueDO::getCode, code);
  30 + }
  31 +
  32 + default List<MesWmMiscIssueDO> selectListByStatus(Integer status) {
  33 + return selectList(MesWmMiscIssueDO::getStatus, status);
  34 + }
  35 +
  36 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -352,11 +352,14 @@ public interface ErrorCodeConstants {
352 352 ErrorCode WM_MATERIAL_REQUEST_STATUS_INVALID = new ErrorCode(1_040_706_001, "领料申请单状态不正确,无法执行该操作");
353 353 ErrorCode WM_MATERIAL_REQUEST_LINE_NOT_EXISTS = new ErrorCode(1_040_706_100, "领料申请单行不存在");
354 354  
355   - // ========== MES 仓库管理-外协出库单(1-040-707-000) ==========
356   - ErrorCode WM_OUTSOURCE_ISSUE_NOT_EXISTS = new ErrorCode(1_040_707_000, "外协出库单不存在");
357   - ErrorCode WM_OUTSOURCE_ISSUE_STATUS_INVALID = new ErrorCode(1_040_707_001, "外协出库单状态不正确,无法执行该操作");
358   - ErrorCode WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH = new ErrorCode(1_040_707_002, "出库单行数量与明细数量不一致");
359   - ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "外协出库单行不存在");
  355 + // ========== MES 仓库管理-外协发料单(1-040-707-000) ==========
  356 + ErrorCode WM_OUTSOURCE_ISSUE_NOT_EXISTS = new ErrorCode(1_040_707_000, "外协发料单不存在");
  357 + ErrorCode WM_OUTSOURCE_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_707_001, "外协发料单编码已存在");
  358 + ErrorCode WM_OUTSOURCE_ISSUE_STATUS_NOT_PREPARE = new ErrorCode(1_040_707_002, "只有草稿状态才允许此操作");
  359 + ErrorCode WM_OUTSOURCE_ISSUE_NO_LINE = new ErrorCode(1_040_707_003, "至少需要一条发料行");
  360 + ErrorCode WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH = new ErrorCode(1_040_707_004, "发料单行数量与明细数量不一致");
  361 + ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "外协发料单行不存在");
  362 + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_707_200, "外协发料单明细不存在");
360 363  
361 364 // ========== MES 仓库管理-生产领料出库单(1-040-708-000) ==========
362 365 ErrorCode WM_PRODUCTION_ISSUE_NOT_EXISTS = new ErrorCode(1_040_708_000, "生产领料出库单不存在");
... ... @@ -414,6 +417,17 @@ public interface ErrorCodeConstants {
414 417 ErrorCode WM_PRODUCT_RECPT_LINE_NOT_EXISTS = new ErrorCode(1_040_712_100, "产品收货单行不存在");
415 418 ErrorCode WM_PRODUCT_RECPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_712_200, "产品收货明细不存在");
416 419  
  420 + // ========== MES 仓库管理-外协入库单(1-040-713-000) ==========
  421 + ErrorCode WM_OUTSOURCE_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_713_000, "外协入库单不存在");
  422 + ErrorCode WM_OUTSOURCE_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_713_001, "外协入库单编码已存在");
  423 + ErrorCode WM_OUTSOURCE_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_713_002, "只有草稿状态才允许此操作");
  424 + ErrorCode WM_OUTSOURCE_RECEIPT_NO_LINE = new ErrorCode(1_040_713_003, "至少需要一条行项目");
  425 + ErrorCode WM_OUTSOURCE_RECEIPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_713_004, "明细上架总数与行入库数量不匹配");
  426 + ErrorCode WM_OUTSOURCE_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_713_005, "入库单状态不正确");
  427 + ErrorCode WM_OUTSOURCE_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_006, "已完成或已取消的入库单不允许取消");
  428 + ErrorCode WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "外协入库单行不存在");
  429 + ErrorCode WM_OUTSOURCE_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "外协入库明细不存在");
  430 +
417 431 // ========== MES 仓库管理-销售退货单(1-040-713-000) ==========
418 432 ErrorCode WM_RETURN_SALES_NOT_EXISTS = new ErrorCode(1_040_713_000, "销售退货单不存在");
419 433 ErrorCode WM_RETURN_SALES_CODE_DUPLICATE = new ErrorCode(1_040_713_001, "销售退货单编码已存在");
... ... @@ -442,6 +456,16 @@ public interface ErrorCodeConstants {
442 456 ErrorCode WM_PRODUCT_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_714_012, "销售出库明细不存在");
443 457 ErrorCode WM_PRODUCT_SALES_STOCK_INSUFFICIENT = new ErrorCode(1_040_714_013, "库存不足,无法拣货");
444 458  
  459 + // ========== MES 仓库管理-杂项出库单(1-040-715-000) ==========
  460 + ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "杂项出库单不存在");
  461 + ErrorCode WM_MISC_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_715_001, "杂项出库单编码已存在");
  462 + ErrorCode WM_MISC_ISSUE_STATUS_INVALID = new ErrorCode(1_040_715_002, "杂项出库单状态不正确,无法执行该操作");
  463 + ErrorCode WM_MISC_ISSUE_NO_LINE = new ErrorCode(1_040_715_003, "杂项出库单至少需要一条行数据");
  464 + ErrorCode WM_MISC_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_715_004, "杂项出库单已完成或已取消,无法取消");
  465 + ErrorCode WM_MISC_ISSUE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_715_005, "杂项出库单行数量与明细数量不一致");
  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, "杂项出库单明细不存在");
  468 +
445 469 // ========== MES 仓库管理-发货通知单(1-040-720-000) ==========
446 470 ErrorCode WM_SALES_NOTICE_NOT_EXISTS = new ErrorCode(1_040_720_000, "发货通知单不存在");
447 471 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/MesWmMiscIssueStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.wm;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * MES 杂项出库单状态枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum MesWmMiscIssueStatusEnum implements ArrayValuable<Integer> {
  17 +
  18 + // 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/MesWmProductSalesStatusEnum.java,关联 orderstatus;然后有“对应方法”
  19 + /**
  20 + * 草稿
  21 + */
  22 + PREPARE(0, "草稿"),
  23 + /**
  24 + * 待执行出库
  25 + */
  26 + APPROVED(1, "待执行出库"),
  27 + /**
  28 + * 已完成
  29 + */
  30 + FINISHED(2, "已完成"),
  31 + /**
  32 + * 已取消
  33 + */
  34 + CANCELED(3, "已取消");
  35 +
  36 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscIssueStatusEnum::getStatus).toArray(Integer[]::new);
  37 +
  38 + /**
  39 + * 状态值
  40 + */
  41 + private final Integer status;
  42 + /**
  43 + * 状态名
  44 + */
  45 + private final String name;
  46 +
  47 + @Override
  48 + public Integer[] array() {
  49 + return ARRAYS;
  50 + }
  51 +
  52 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * MES 杂项出库单行 Service 接口
  13 + */
  14 +public interface MesWmMiscIssueLineService {
  15 +
  16 + /**
  17 + * 创建杂项出库单行
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createMiscIssueLine(@Valid MesWmMiscIssueLineSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 修改杂项出库单行
  26 + *
  27 + * @param updateReqVO 修改信息
  28 + */
  29 + void updateMiscIssueLine(@Valid MesWmMiscIssueLineSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除杂项出库单行(级联删除明细)
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deleteMiscIssueLine(Long id);
  37 +
  38 + /**
  39 + * 获得杂项出库单行
  40 + *
  41 + * @param id 编号
  42 + * @return 杂项出库单行
  43 + */
  44 + MesWmMiscIssueLineDO getMiscIssueLine(Long id);
  45 +
  46 + /**
  47 + * 获得杂项出库单行分页
  48 + *
  49 + * @param pageReqVO 分页参数
  50 + * @return 杂项出库单行分页
  51 + */
  52 + PageResult<MesWmMiscIssueLineDO> getMiscIssueLinePage(MesWmMiscIssueLinePageReqVO pageReqVO);
  53 +
  54 + /**
  55 + * 按出库单编号获得行列表
  56 + *
  57 + * @param issueId 出库单编号
  58 + * @return 行列表
  59 + */
  60 + List<MesWmMiscIssueLineDO> getMiscIssueLineListByIssueId(Long issueId);
  61 +
  62 + /**
  63 + * 按出库单编号批量删除行
  64 + *
  65 + * @param issueId 出库单编号
  66 + */
  67 + void deleteMiscIssueLineByIssueId(Long issueId);
  68 +
  69 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscissue;
  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.miscissue.vo.line.MesWmMiscIssueLinePageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
  8 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueLineMapper;
  9 +import jakarta.annotation.Resource;
  10 +import org.springframework.context.annotation.Lazy;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.transaction.annotation.Transactional;
  13 +import org.springframework.validation.annotation.Validated;
  14 +
  15 +import java.util.List;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  18 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  19 +
  20 +/**
  21 + * MES 杂项出库单行 Service 实现类
  22 + */
  23 +@Service
  24 +@Validated
  25 +public class MesWmMiscIssueLineServiceImpl implements MesWmMiscIssueLineService {
  26 +
  27 + @Resource
  28 + private MesWmMiscIssueLineMapper miscIssueLineMapper;
  29 +
  30 + @Resource
  31 + @Lazy
  32 + private MesWmMiscIssueService miscIssueService;
  33 +
  34 + @Override
  35 + public Long createMiscIssueLine(MesWmMiscIssueLineSaveReqVO createReqVO) {
  36 + // 校验父单据存在且为可编辑状态
  37 + miscIssueService.validateMiscIssueEditable(createReqVO.getIssueId());
  38 + // TODO AI:item 存在;
  39 + // TODO @AI:校验 areaid 等字段存在;areaservice 有统一方法;
  40 +
  41 + // 新增
  42 + MesWmMiscIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscIssueLineDO.class);
  43 + miscIssueLineMapper.insert(line);
  44 + return line.getId();
  45 + }
  46 +
  47 + @Override
  48 + public void updateMiscIssueLine(MesWmMiscIssueLineSaveReqVO updateReqVO) {
  49 + // 校验存在
  50 + MesWmMiscIssueLineDO line = validateMiscIssueLineExists(updateReqVO.getId());
  51 + // 校验父单据存在且为可编辑状态
  52 + miscIssueService.validateMiscIssueEditable(line.getIssueId());
  53 + // TODO AI:item 存在;
  54 + // TODO @AI:校验 areaid 等字段存在;areaservice 有统一方法;
  55 +
  56 + // 更新
  57 + MesWmMiscIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueLineDO.class);
  58 + miscIssueLineMapper.updateById(updateObj);
  59 + }
  60 +
  61 + @Override
  62 + @Transactional(rollbackFor = Exception.class)
  63 + public void deleteMiscIssueLine(Long id) {
  64 + // 校验存在
  65 + validateMiscIssueLineExists(id);
  66 +
  67 + // 删除
  68 + miscIssueLineMapper.deleteById(id);
  69 + }
  70 +
  71 + @Override
  72 + public MesWmMiscIssueLineDO getMiscIssueLine(Long id) {
  73 + return miscIssueLineMapper.selectById(id);
  74 + }
  75 +
  76 + @Override
  77 + public PageResult<MesWmMiscIssueLineDO> getMiscIssueLinePage(MesWmMiscIssueLinePageReqVO pageReqVO) {
  78 + return miscIssueLineMapper.selectPage(pageReqVO);
  79 + }
  80 +
  81 + @Override
  82 + public List<MesWmMiscIssueLineDO> getMiscIssueLineListByIssueId(Long issueId) {
  83 + return miscIssueLineMapper.selectListByIssueId(issueId);
  84 + }
  85 +
  86 + @Override
  87 + public void deleteMiscIssueLineByIssueId(Long issueId) {
  88 + miscIssueLineMapper.deleteByIssueId(issueId);
  89 + }
  90 +
  91 + private MesWmMiscIssueLineDO validateMiscIssueLineExists(Long id) {
  92 + MesWmMiscIssueLineDO line = miscIssueLineMapper.selectById(id);
  93 + if (line == null) {
  94 + throw exception(WM_MISC_ISSUE_LINE_NOT_EXISTS);
  95 + }
  96 + return line;
  97 + }
  98 +
  99 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscissue;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +/**
  10 + * MES 杂项出库单 Service 接口
  11 + */
  12 +public interface MesWmMiscIssueService {
  13 +
  14 + /**
  15 + * 创建杂项出库单
  16 + *
  17 + * @param createReqVO 创建信息
  18 + * @return 编号
  19 + */
  20 + Long createMiscIssue(@Valid MesWmMiscIssueSaveReqVO createReqVO);
  21 +
  22 + /**
  23 + * 修改杂项出库单
  24 + *
  25 + * @param updateReqVO 修改信息
  26 + */
  27 + void updateMiscIssue(@Valid MesWmMiscIssueSaveReqVO updateReqVO);
  28 +
  29 + /**
  30 + * 删除杂项出库单(级联删除行+明细)
  31 + *
  32 + * @param id 编号
  33 + */
  34 + void deleteMiscIssue(Long id);
  35 +
  36 + /**
  37 + * 获得杂项出库单
  38 + *
  39 + * @param id 编号
  40 + * @return 杂项出库单
  41 + */
  42 + MesWmMiscIssueDO getMiscIssue(Long id);
  43 +
  44 + /**
  45 + * 获得杂项出库单分页
  46 + *
  47 + * @param pageReqVO 分页参数
  48 + * @return 杂项出库单分页
  49 + */
  50 + PageResult<MesWmMiscIssueDO> getMiscIssuePage(MesWmMiscIssuePageReqVO pageReqVO);
  51 +
  52 + /**
  53 + * 提交杂项出库单(草稿 → 待执行出库)
  54 + *
  55 + * @param id 编号
  56 + */
  57 + void submitMiscIssue(Long id);
  58 +
  59 + /**
  60 + * 执行出库(待执行出库 → 已完成),扣减库存
  61 + *
  62 + * @param id 编号
  63 + */
  64 + void finishMiscIssue(Long id);
  65 +
  66 + /**
  67 + * 取消杂项出库单(任意非已完成/已取消状态 → 已取消)
  68 + *
  69 + * @param id 编号
  70 + */
  71 + void cancelMiscIssue(Long id);
  72 +
  73 + /**
  74 + * 校验杂项出库单存在且处于可编辑状态(草稿)
  75 + *
  76 + * @param id 编号
  77 + * @return 杂项出库单
  78 + */
  79 + MesWmMiscIssueDO validateMiscIssueEditable(Long id);
  80 +
  81 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.miscissue;
  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.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  8 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO;
  13 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueMapper;
  14 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueStatusEnum;
  15 +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
  16 +import jakarta.annotation.Resource;
  17 +import lombok.extern.slf4j.Slf4j;
  18 +import org.springframework.stereotype.Service;
  19 +import org.springframework.transaction.annotation.Transactional;
  20 +import org.springframework.validation.annotation.Validated;
  21 +
  22 +import java.math.BigDecimal;
  23 +import java.util.List;
  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 +@Service
  32 +@Validated
  33 +@Slf4j
  34 +public class MesWmMiscIssueServiceImpl implements MesWmMiscIssueService {
  35 +
  36 + @Resource
  37 + private MesWmMiscIssueMapper miscIssueMapper;
  38 +
  39 + @Resource
  40 + private MesWmMiscIssueLineService miscIssueLineService;
  41 +
  42 + @Resource
  43 + private MesWmMaterialStockService materialStockService;
  44 +
  45 + @Override
  46 + public Long createMiscIssue(MesWmMiscIssueSaveReqVO createReqVO) {
  47 + // 校验编码唯一
  48 + validateCodeUnique(null, createReqVO.getCode());
  49 +
  50 + // 插入
  51 + MesWmMiscIssueDO issue = BeanUtils.toBean(createReqVO, MesWmMiscIssueDO.class);
  52 + issue.setStatus(MesWmMiscIssueStatusEnum.PREPARE.getStatus());
  53 + miscIssueMapper.insert(issue);
  54 + return issue.getId();
  55 + }
  56 +
  57 + @Override
  58 + public void updateMiscIssue(MesWmMiscIssueSaveReqVO updateReqVO) {
  59 + // 校验存在 + 草稿状态
  60 + validateMiscIssueExistsAndDraft(updateReqVO.getId());
  61 + // 校验编码唯一
  62 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
  63 +
  64 + // 更新
  65 + MesWmMiscIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueDO.class);
  66 + miscIssueMapper.updateById(updateObj);
  67 + }
  68 +
  69 + @Override
  70 + @Transactional(rollbackFor = Exception.class)
  71 + public void deleteMiscIssue(Long id) {
  72 + // 校验存在 + 草稿状态
  73 + validateMiscIssueExistsAndDraft(id);
  74 +
  75 + // 级联删除行
  76 + miscIssueLineService.deleteMiscIssueLineByIssueId(id);
  77 + // 删除
  78 + miscIssueMapper.deleteById(id);
  79 + }
  80 +
  81 + @Override
  82 + public MesWmMiscIssueDO getMiscIssue(Long id) {
  83 + return miscIssueMapper.selectById(id);
  84 + }
  85 +
  86 + @Override
  87 + public PageResult<MesWmMiscIssueDO> getMiscIssuePage(MesWmMiscIssuePageReqVO pageReqVO) {
  88 + return miscIssueMapper.selectPage(pageReqVO);
  89 + }
  90 +
  91 + @Override
  92 + @Transactional(rollbackFor = Exception.class)
  93 + public void submitMiscIssue(Long id) {
  94 + // 校验存在 + 草稿状态
  95 + validateMiscIssueExistsAndDraft(id);
  96 + // 校验至少有一条行
  97 + List<MesWmMiscIssueLineDO> lines = miscIssueLineService.getMiscIssueLineListByIssueId(id);
  98 + if (CollUtil.isEmpty(lines)) {
  99 + throw exception(WM_MISC_ISSUE_NO_LINE);
  100 + }
  101 +
  102 + // 提交(草稿 → 待执行出库)
  103 + miscIssueMapper.updateById(new MesWmMiscIssueDO()
  104 + .setId(id).setStatus(MesWmMiscIssueStatusEnum.APPROVED.getStatus()));
  105 + }
  106 +
  107 + @Override
  108 + @Transactional(rollbackFor = Exception.class)
  109 + public void finishMiscIssue(Long id) {
  110 + // 校验存在
  111 + MesWmMiscIssueDO issue = validateMiscIssueExists(id);
  112 + if (ObjUtil.notEqual(MesWmMiscIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) {
  113 + throw exception(WM_MISC_ISSUE_STATUS_INVALID);
  114 + }
  115 +
  116 + // 遍历所有行,扣减库存
  117 + // TODO @AI:需要实现 materialStockService.decreaseStock 方法来扣减库存
  118 + List<MesWmMiscIssueLineDO> lines = miscIssueLineService.getMiscIssueLineListByIssueId(id);
  119 + for (MesWmMiscIssueLineDO line : lines) {
  120 + // materialStockService.decreaseStock(
  121 + // line.getItemId(), line.getWarehouseId(), line.getLocationId(), line.getAreaId(),
  122 + // line.getBatchId(), line.getQuantity());
  123 + log.warn("[finishMiscIssue][杂项出库单({}) 行({}) 需要扣减库存,但 decreaseStock 方法尚未实现]", id, line.getId());
  124 + }
  125 +
  126 + // 更新出库单状态(待执行出库 → 已完成)
  127 + miscIssueMapper.updateById(new MesWmMiscIssueDO()
  128 + .setId(id).setStatus(MesWmMiscIssueStatusEnum.FINISHED.getStatus()));
  129 + }
  130 +
  131 + @Override
  132 + @Transactional(rollbackFor = Exception.class)
  133 + public void cancelMiscIssue(Long id) {
  134 + // 校验存在
  135 + MesWmMiscIssueDO issue = validateMiscIssueExists(id);
  136 + // 已完成和已取消不允许取消
  137 + if (ObjectUtils.equalsAny(issue.getStatus(),
  138 + MesWmMiscIssueStatusEnum.FINISHED.getStatus(),
  139 + MesWmMiscIssueStatusEnum.CANCELED.getStatus())) {
  140 + throw exception(WM_MISC_ISSUE_CANCEL_NOT_ALLOWED);
  141 + }
  142 + // 取消
  143 + miscIssueMapper.updateById(new MesWmMiscIssueDO()
  144 + .setId(id).setStatus(MesWmMiscIssueStatusEnum.CANCELED.getStatus()));
  145 + }
  146 +
  147 + @Override
  148 + public MesWmMiscIssueDO validateMiscIssueEditable(Long id) {
  149 + MesWmMiscIssueDO issue = validateMiscIssueExists(id);
  150 + if (ObjUtil.notEqual(issue.getStatus(), MesWmMiscIssueStatusEnum.PREPARE.getStatus())) {
  151 + throw exception(WM_MISC_ISSUE_STATUS_INVALID);
  152 + }
  153 + return issue;
  154 + }
  155 +
  156 + private MesWmMiscIssueDO validateMiscIssueExists(Long id) {
  157 + MesWmMiscIssueDO issue = miscIssueMapper.selectById(id);
  158 + if (issue == null) {
  159 + throw exception(WM_MISC_ISSUE_NOT_EXISTS);
  160 + }
  161 + return issue;
  162 + }
  163 +
  164 + /**
  165 + * 校验杂项出库单存在且为草稿状态
  166 + */
  167 + private MesWmMiscIssueDO validateMiscIssueExistsAndDraft(Long id) {
  168 + MesWmMiscIssueDO issue = validateMiscIssueExists(id);
  169 + if (ObjUtil.notEqual(MesWmMiscIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) {
  170 + throw exception(WM_MISC_ISSUE_STATUS_INVALID);
  171 + }
  172 + return issue;
  173 + }
  174 +
  175 + private void validateCodeUnique(Long id, String code) {
  176 + MesWmMiscIssueDO issue = miscIssueMapper.selectByCode(code);
  177 + if (issue == null) {
  178 + return;
  179 + }
  180 + if (ObjUtil.notEqual(id, issue.getId())) {
  181 + throw exception(WM_MISC_ISSUE_CODE_DUPLICATE);
  182 + }
  183 + }
  184 +
  185 +}
... ...