Commit abddf4a1c402cd3babd791fbcc18656bae758459

Authored by YunaiV
1 parent 0a5d44f7

✨ feat(mes): 添加装箱单及装箱明细相关功能

新增装箱单和装箱明细的请求和响应对象,完善装箱单的创建、更新、删除及查询功能。
同时,增加装箱单状态的枚举和相关逻辑,提升系统的可用性和扩展性。
Showing 17 changed files with 1368 additions and 2 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/MesWmPackageController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage;
  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.collection.MapUtils;
  9 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  10 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  11 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackagePageReqVO;
  12 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackageRespVO;
  13 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackageSaveReqVO;
  14 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
  15 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  16 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageDO;
  17 +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
  18 +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
  19 +import cn.iocoder.yudao.module.mes.service.wm.wmpackage.MesWmPackageService;
  20 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  21 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  22 +import io.swagger.v3.oas.annotations.Operation;
  23 +import io.swagger.v3.oas.annotations.Parameter;
  24 +import io.swagger.v3.oas.annotations.tags.Tag;
  25 +import jakarta.annotation.Resource;
  26 +import jakarta.servlet.http.HttpServletResponse;
  27 +import jakarta.validation.Valid;
  28 +import org.springframework.security.access.prepost.PreAuthorize;
  29 +import org.springframework.validation.annotation.Validated;
  30 +import org.springframework.web.bind.annotation.*;
  31 +
  32 +import java.io.IOException;
  33 +import java.util.*;
  34 +import java.util.stream.Collectors;
  35 +
  36 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  37 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  38 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  39 +
  40 +@Tag(name = "管理后台 - MES 装箱单")
  41 +@RestController
  42 +@RequestMapping("/mes/wm/package")
  43 +@Validated
  44 +public class MesWmPackageController {
  45 +
  46 + @Resource
  47 + private MesWmPackageService packageService;
  48 + @Resource
  49 + private MesMdClientService clientService;
  50 + @Resource
  51 + private MesMdUnitMeasureService unitMeasureService;
  52 + @Resource
  53 + private AdminUserApi adminUserApi;
  54 +
  55 + @PostMapping("/create")
  56 + @Operation(summary = "创建装箱单")
  57 + @PreAuthorize("@ss.hasPermission('mes:wm-package:create')")
  58 + public CommonResult<Long> createPackage(@Valid @RequestBody MesWmPackageSaveReqVO createReqVO) {
  59 + return success(packageService.createPackage(createReqVO));
  60 + }
  61 +
  62 + @PutMapping("/update")
  63 + @Operation(summary = "修改装箱单")
  64 + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')")
  65 + public CommonResult<Boolean> updatePackage(@Valid @RequestBody MesWmPackageSaveReqVO updateReqVO) {
  66 + packageService.updatePackage(updateReqVO);
  67 + return success(true);
  68 + }
  69 +
  70 + @DeleteMapping("/delete")
  71 + @Operation(summary = "删除装箱单")
  72 + @Parameter(name = "id", description = "编号", required = true)
  73 + @PreAuthorize("@ss.hasPermission('mes:wm-package:delete')")
  74 + public CommonResult<Boolean> deletePackage(@RequestParam("id") Long id) {
  75 + packageService.deletePackage(id);
  76 + return success(true);
  77 + }
  78 +
  79 + @GetMapping("/get")
  80 + @Operation(summary = "获得装箱单")
  81 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  82 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  83 + public CommonResult<MesWmPackageRespVO> getPackage(@RequestParam("id") Long id) {
  84 + MesWmPackageDO packageDO = packageService.getPackage(id);
  85 + if (packageDO == null) {
  86 + return success(null);
  87 + }
  88 + return success(buildRespVOList(Collections.singletonList(packageDO)).get(0));
  89 + }
  90 +
  91 + @GetMapping("/page")
  92 + @Operation(summary = "获得装箱单分页")
  93 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  94 + public CommonResult<PageResult<MesWmPackageRespVO>> getPackagePage(
  95 + @Valid MesWmPackagePageReqVO pageReqVO) {
  96 + PageResult<MesWmPackageDO> pageResult = packageService.getPackagePage(pageReqVO);
  97 + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
  98 + }
  99 +
  100 + @GetMapping("/export-excel")
  101 + @Operation(summary = "导出装箱单 Excel")
  102 + @PreAuthorize("@ss.hasPermission('mes:wm-package:export')")
  103 + @ApiAccessLog(operateType = EXPORT)
  104 + public void exportPackageExcel(@Valid MesWmPackagePageReqVO pageReqVO,
  105 + HttpServletResponse response) throws IOException {
  106 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  107 + PageResult<MesWmPackageDO> pageResult = packageService.getPackagePage(pageReqVO);
  108 + ExcelUtils.write(response, "装箱单.xls", "数据", MesWmPackageRespVO.class,
  109 + buildRespVOList(pageResult.getList()));
  110 + }
  111 +
  112 + @PutMapping("/finish")
  113 + @Operation(summary = "完成装箱单")
  114 + @Parameter(name = "id", description = "编号", required = true)
  115 + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')")
  116 + public CommonResult<Boolean> finishPackage(@RequestParam("id") Long id) {
  117 + packageService.finishPackage(id);
  118 + return success(true);
  119 + }
  120 +
  121 + @GetMapping("/tree")
  122 + @Operation(summary = "获得装箱单树形结构")
  123 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  124 + public CommonResult<List<MesWmPackageRespVO>> getPackageTree() {
  125 + List<MesWmPackageDO> list = packageService.getPackageTree();
  126 + List<MesWmPackageRespVO> voList = buildRespVOList(list);
  127 + // 构建树形结构
  128 + return success(buildTree(voList));
  129 + }
  130 +
  131 + // ========== 私有方法 ==========
  132 +
  133 + private List<MesWmPackageRespVO> buildRespVOList(List<MesWmPackageDO> list) {
  134 + if (CollUtil.isEmpty(list)) {
  135 + return Collections.emptyList();
  136 + }
  137 + // 批量查询客户
  138 + Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
  139 + convertSet(list, MesWmPackageDO::getClientId));
  140 + // 批量查询计量单位(尺寸 + 重量)
  141 + Set<Long> unitIds = new HashSet<>();
  142 + list.forEach(p -> {
  143 + if (p.getSizeUnitId() != null) {
  144 + unitIds.add(p.getSizeUnitId());
  145 + }
  146 + if (p.getWeightUnitId() != null) {
  147 + unitIds.add(p.getWeightUnitId());
  148 + }
  149 + });
  150 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(unitIds);
  151 + // 批量查询检查员
  152 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  153 + convertSet(list, MesWmPackageDO::getInspectorUserId));
  154 +
  155 + return BeanUtils.toBean(list, MesWmPackageRespVO.class, vo -> {
  156 + MapUtils.findAndThen(clientMap, vo.getClientId(),
  157 + client -> vo.setClientCode(client.getCode()).setClientName(client.getName())
  158 + .setClientNickname(client.getNickname()));
  159 + MapUtils.findAndThen(unitMeasureMap, vo.getSizeUnitId(),
  160 + unit -> vo.setSizeUnitName(unit.getName()));
  161 + MapUtils.findAndThen(unitMeasureMap, vo.getWeightUnitId(),
  162 + unit -> vo.setWeightUnitName(unit.getName()));
  163 + MapUtils.findAndThen(userMap, vo.getInspectorUserId(),
  164 + user -> vo.setInspectorName(user.getNickname()));
  165 + });
  166 + }
  167 +
  168 + private List<MesWmPackageRespVO> buildTree(List<MesWmPackageRespVO> list) {
  169 + // 按 parentId 分组
  170 + Map<Long, List<MesWmPackageRespVO>> parentMap = list.stream()
  171 + .collect(Collectors.groupingBy(vo -> vo.getParentId() != null ? vo.getParentId() : 0L));
  172 + // 设置 children
  173 + list.forEach(vo -> vo.setChildren(parentMap.get(vo.getId())));
  174 + // 返回顶级节点(parentId == 0 或 parentId == null)
  175 + return list.stream()
  176 + .filter(vo -> vo.getParentId() == null || vo.getParentId() == 0L)
  177 + .collect(Collectors.toList());
  178 + }
  179 +
  180 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/MesWmPackageLineController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage;
  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.wmpackage.vo.line.MesWmPackageLinePageReqVO;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLineRespVO;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLineSaveReqVO;
  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.pro.workorder.MesProWorkOrderDO;
  14 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
  15 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
  16 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;
  17 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageLineDO;
  18 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  19 +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
  20 +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
  21 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
  22 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService;
  23 +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService;
  24 +import cn.iocoder.yudao.module.mes.service.wm.wmpackage.MesWmPackageLineService;
  25 +import io.swagger.v3.oas.annotations.Operation;
  26 +import io.swagger.v3.oas.annotations.Parameter;
  27 +import io.swagger.v3.oas.annotations.tags.Tag;
  28 +import jakarta.annotation.Resource;
  29 +import jakarta.validation.Valid;
  30 +import org.springframework.security.access.prepost.PreAuthorize;
  31 +import org.springframework.validation.annotation.Validated;
  32 +import org.springframework.web.bind.annotation.*;
  33 +
  34 +import java.util.Collections;
  35 +import java.util.List;
  36 +import java.util.Map;
  37 +
  38 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  39 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  40 +
  41 +@Tag(name = "管理后台 - MES 装箱明细")
  42 +@RestController
  43 +@RequestMapping("/mes/wm/package-line")
  44 +@Validated
  45 +public class MesWmPackageLineController {
  46 +
  47 + @Resource
  48 + private MesWmPackageLineService packageLineService;
  49 + @Resource
  50 + private MesMdItemService itemService;
  51 + @Resource
  52 + private MesMdUnitMeasureService unitMeasureService;
  53 + @Resource
  54 + private MesProWorkOrderService workOrderService;
  55 + @Resource
  56 + private MesWmWarehouseService warehouseService;
  57 + @Resource
  58 + private MesWmWarehouseLocationService locationService;
  59 + @Resource
  60 + private MesWmWarehouseAreaService areaService;
  61 +
  62 + @PostMapping("/create")
  63 + @Operation(summary = "创建装箱明细")
  64 + @PreAuthorize("@ss.hasPermission('mes:wm-package:create')")
  65 + public CommonResult<Long> createPackageLine(@Valid @RequestBody MesWmPackageLineSaveReqVO createReqVO) {
  66 + return success(packageLineService.createPackageLine(createReqVO));
  67 + }
  68 +
  69 + @PutMapping("/update")
  70 + @Operation(summary = "修改装箱明细")
  71 + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')")
  72 + public CommonResult<Boolean> updatePackageLine(@Valid @RequestBody MesWmPackageLineSaveReqVO updateReqVO) {
  73 + packageLineService.updatePackageLine(updateReqVO);
  74 + return success(true);
  75 + }
  76 +
  77 + @DeleteMapping("/delete")
  78 + @Operation(summary = "删除装箱明细")
  79 + @Parameter(name = "id", description = "编号", required = true)
  80 + @PreAuthorize("@ss.hasPermission('mes:wm-package:delete')")
  81 + public CommonResult<Boolean> deletePackageLine(@RequestParam("id") Long id) {
  82 + packageLineService.deletePackageLine(id);
  83 + return success(true);
  84 + }
  85 +
  86 + @GetMapping("/get")
  87 + @Operation(summary = "获得装箱明细")
  88 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  89 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  90 + public CommonResult<MesWmPackageLineRespVO> getPackageLine(@RequestParam("id") Long id) {
  91 + MesWmPackageLineDO line = packageLineService.getPackageLine(id);
  92 + if (line == null) {
  93 + return success(null);
  94 + }
  95 + return success(buildRespVOList(Collections.singletonList(line)).get(0));
  96 + }
  97 +
  98 + @GetMapping("/page")
  99 + @Operation(summary = "获得装箱明细分页")
  100 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  101 + public CommonResult<PageResult<MesWmPackageLineRespVO>> getPackageLinePage(
  102 + @Valid MesWmPackageLinePageReqVO pageReqVO) {
  103 + PageResult<MesWmPackageLineDO> pageResult = packageLineService.getPackageLinePage(pageReqVO);
  104 + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
  105 + }
  106 +
  107 + @GetMapping("/list-by-package-id")
  108 + @Operation(summary = "根据装箱单 ID 获得明细列表")
  109 + @Parameter(name = "packageId", description = "装箱单 ID", required = true, example = "1024")
  110 + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
  111 + public CommonResult<List<MesWmPackageLineRespVO>> getPackageLineListByPackageId(
  112 + @RequestParam("packageId") Long packageId) {
  113 + List<MesWmPackageLineDO> list = packageLineService.getPackageLineListByPackageId(packageId);
  114 + return success(buildRespVOList(list));
  115 + }
  116 +
  117 + // ========== 私有方法 ==========
  118 +
  119 + private List<MesWmPackageLineRespVO> buildRespVOList(List<MesWmPackageLineDO> list) {
  120 + if (CollUtil.isEmpty(list)) {
  121 + return Collections.emptyList();
  122 + }
  123 + // 批量查询物料
  124 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
  125 + convertSet(list, MesWmPackageLineDO::getItemId));
  126 + // 批量查询计量单位
  127 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  128 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  129 + // 批量查询工单
  130 + Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
  131 + convertSet(list, MesWmPackageLineDO::getWorkOrderId));
  132 + // 批量查询仓库
  133 + Map<Long, MesWmWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
  134 + convertSet(list, MesWmPackageLineDO::getWarehouseId));
  135 + // 批量查询库区
  136 + Map<Long, MesWmWarehouseLocationDO> locationMap = locationService.getWarehouseLocationMap(
  137 + convertSet(list, MesWmPackageLineDO::getLocationId));
  138 + // 批量查询库位
  139 + Map<Long, MesWmWarehouseAreaDO> areaMap = areaService.getWarehouseAreaMap(
  140 + convertSet(list, MesWmPackageLineDO::getAreaId));
  141 + // 拼接数据
  142 + return BeanUtils.toBean(list, MesWmPackageLineRespVO.class, vo -> {
  143 + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
  144 + vo.setItemCode(item.getCode()).setItemName(item.getName())
  145 + .setSpecification(item.getSpecification());
  146 + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  147 + unit -> vo.setUnitMeasureName(unit.getName()));
  148 + });
  149 + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(),
  150 + workOrder -> vo.setWorkOrderCode(workOrder.getCode()).setBatchCode(workOrder.getBatchCode()));
  151 + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(),
  152 + warehouse -> vo.setWarehouseName(warehouse.getName()));
  153 + MapUtils.findAndThen(locationMap, vo.getLocationId(),
  154 + location -> vo.setLocationName(location.getName()));
  155 + MapUtils.findAndThen(areaMap, vo.getAreaId(),
  156 + area -> vo.setAreaName(area.getName()));
  157 + });
  158 + }
  159 +
  160 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/MesWmPackagePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.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 lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDate;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
  13 +
  14 +@Schema(description = "管理后台 - MES 装箱单分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class MesWmPackagePageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "装箱单编号", example = "PKG")
  21 + private String code;
  22 +
  23 + @Schema(description = "销售订单编号", example = "SO")
  24 + private String soCode;
  25 +
  26 + @Schema(description = "客户 ID", example = "1")
  27 + private Long clientId;
  28 +
  29 + @Schema(description = "装箱日期")
  30 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  31 + private LocalDate[] packageDate;
  32 +
  33 + @Schema(description = "状态", example = "0")
  34 + private Integer status;
  35 +
  36 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/MesWmPackageRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo;
  2 +
  3 +import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
  4 +import cn.idev.excel.annotation.ExcelProperty;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.Data;
  7 +import lombok.experimental.Accessors;
  8 +
  9 +import java.math.BigDecimal;
  10 +import java.time.LocalDate;
  11 +import java.time.LocalDateTime;
  12 +import java.util.List;
  13 +
  14 +@Schema(description = "管理后台 - MES 装箱单 Response VO")
  15 +@Data
  16 +@Accessors(chain = true)
  17 +@ExcelIgnoreUnannotated
  18 +public class MesWmPackageRespVO {
  19 +
  20 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  21 + @ExcelProperty("编号")
  22 + private Long id;
  23 +
  24 + @Schema(description = "装箱单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PKG20260307001")
  25 + @ExcelProperty("装箱单编号")
  26 + private String code;
  27 +
  28 + @Schema(description = "父箱 ID", example = "0")
  29 + private Long parentId;
  30 +
  31 + @Schema(description = "装箱日期")
  32 + @ExcelProperty("装箱日期")
  33 + private LocalDate packageDate;
  34 +
  35 + @Schema(description = "销售订单编号", example = "SO20260301")
  36 + @ExcelProperty("销售订单编号")
  37 + private String soCode;
  38 +
  39 + @Schema(description = "发票编号", example = "INV20260301")
  40 + @ExcelProperty("发票编号")
  41 + private String invoiceCode;
  42 +
  43 + @Schema(description = "客户 ID", example = "1")
  44 + private Long clientId;
  45 +
  46 + @Schema(description = "客户编码", example = "C001")
  47 + @ExcelProperty("客户编码")
  48 + private String clientCode;
  49 +
  50 + @Schema(description = "客户名称", example = "某客户")
  51 + @ExcelProperty("客户名称")
  52 + private String clientName;
  53 +
  54 + @Schema(description = "客户简称", example = "某客户简称")
  55 + private String clientNickname;
  56 +
  57 + @Schema(description = "箱长度", example = "60.00")
  58 + @ExcelProperty("箱长度")
  59 + private BigDecimal length;
  60 +
  61 + @Schema(description = "箱宽度", example = "40.00")
  62 + @ExcelProperty("箱宽度")
  63 + private BigDecimal width;
  64 +
  65 + @Schema(description = "箱高度", example = "30.00")
  66 + @ExcelProperty("箱高度")
  67 + private BigDecimal height;
  68 +
  69 + @Schema(description = "尺寸单位 ID", example = "1")
  70 + private Long sizeUnitId;
  71 +
  72 + @Schema(description = "尺寸单位名称", example = "厘米")
  73 + @ExcelProperty("尺寸单位")
  74 + private String sizeUnitName;
  75 +
  76 + @Schema(description = "净重", example = "10.00")
  77 + @ExcelProperty("净重")
  78 + private BigDecimal netWeight;
  79 +
  80 + @Schema(description = "毛重", example = "12.00")
  81 + @ExcelProperty("毛重")
  82 + private BigDecimal grossWeight;
  83 +
  84 + @Schema(description = "重量单位 ID", example = "2")
  85 + private Long weightUnitId;
  86 +
  87 + @Schema(description = "重量单位名称", example = "千克")
  88 + @ExcelProperty("重量单位")
  89 + private String weightUnitName;
  90 +
  91 + @Schema(description = "检查员用户 ID", example = "1")
  92 + private Long inspectorUserId;
  93 +
  94 + @Schema(description = "检查员姓名", example = "张三")
  95 + @ExcelProperty("检查员")
  96 + private String inspectorName;
  97 +
  98 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  99 + @ExcelProperty("状态")
  100 + private Integer status;
  101 +
  102 + @Schema(description = "备注", example = "备注")
  103 + @ExcelProperty("备注")
  104 + private String remark;
  105 +
  106 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  107 + @ExcelProperty("创建时间")
  108 + private LocalDateTime createTime;
  109 +
  110 + @Schema(description = "子箱列表")
  111 + private List<MesWmPackageRespVO> children;
  112 +
  113 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/MesWmPackageSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +import java.math.BigDecimal;
  9 +import java.time.LocalDate;
  10 +
  11 +@Schema(description = "管理后台 - MES 装箱单新增/修改 Request VO")
  12 +@Data
  13 +public class MesWmPackageSaveReqVO {
  14 +
  15 + @Schema(description = "编号", example = "1024")
  16 + private Long id;
  17 +
  18 + @Schema(description = "装箱单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PKG20260307001")
  19 + @NotEmpty(message = "装箱单编号不能为空")
  20 + private String code;
  21 +
  22 + @Schema(description = "父箱 ID", example = "0")
  23 + private Long parentId;
  24 +
  25 + @Schema(description = "装箱日期", requiredMode = Schema.RequiredMode.REQUIRED)
  26 + @NotNull(message = "装箱日期不能为空")
  27 + private LocalDate packageDate;
  28 +
  29 + @Schema(description = "销售订单编号", example = "SO20260301")
  30 + private String soCode;
  31 +
  32 + @Schema(description = "发票编号", example = "INV20260301")
  33 + private String invoiceCode;
  34 +
  35 + @Schema(description = "客户 ID", example = "1")
  36 + private Long clientId;
  37 +
  38 + @Schema(description = "箱长度", example = "60.00")
  39 + private BigDecimal length;
  40 +
  41 + @Schema(description = "箱宽度", example = "40.00")
  42 + private BigDecimal width;
  43 +
  44 + @Schema(description = "箱高度", example = "30.00")
  45 + private BigDecimal height;
  46 +
  47 + @Schema(description = "尺寸单位 ID", example = "1")
  48 + private Long sizeUnitId;
  49 +
  50 + @Schema(description = "净重", example = "10.00")
  51 + private BigDecimal netWeight;
  52 +
  53 + @Schema(description = "毛重", example = "12.00")
  54 + private BigDecimal grossWeight;
  55 +
  56 + @Schema(description = "重量单位 ID", example = "2")
  57 + private Long weightUnitId;
  58 +
  59 + @Schema(description = "检查员用户 ID", example = "1")
  60 + private Long inspectorUserId;
  61 +
  62 + @Schema(description = "备注", example = "备注")
  63 + private String remark;
  64 +
  65 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/line/MesWmPackageLinePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.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 MesWmPackageLinePageReqVO extends PageParam {
  15 +
  16 + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotNull(message = "装箱单 ID 不能为空")
  18 + private Long packageId;
  19 +
  20 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/line/MesWmPackageLineRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.experimental.Accessors;
  6 +
  7 +import java.math.BigDecimal;
  8 +import java.time.LocalDate;
  9 +import java.time.LocalDateTime;
  10 +
  11 +@Schema(description = "管理后台 - MES 装箱明细 Response VO")
  12 +@Data
  13 +@Accessors(chain = true)
  14 +public class MesWmPackageLineRespVO {
  15 +
  16 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  17 + private Long id;
  18 +
  19 + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  20 + private Long packageId;
  21 +
  22 + @Schema(description = "库存记录 ID", example = "1")
  23 + private Long materialStockId;
  24 +
  25 + @Schema(description = "产品物料 ID", 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 = "M10*50")
  35 + private String specification;
  36 +
  37 + @Schema(description = "计量单位名称", example = "个")
  38 + private String unitMeasureName;
  39 +
  40 + @Schema(description = "装箱数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
  41 + private BigDecimal quantity;
  42 +
  43 + @Schema(description = "生产工单 ID", example = "1")
  44 + private Long workOrderId;
  45 +
  46 + @Schema(description = "生产工单编号", example = "WO20260301")
  47 + private String workOrderCode;
  48 +
  49 + @Schema(description = "批次号", example = "BATCH001")
  50 + private String batchCode;
  51 +
  52 + @Schema(description = "仓库 ID", example = "1")
  53 + private Long warehouseId;
  54 +
  55 + @Schema(description = "仓库名称", example = "成品仓")
  56 + private String warehouseName;
  57 +
  58 + @Schema(description = "库区 ID", example = "1")
  59 + private Long locationId;
  60 +
  61 + @Schema(description = "库区名称", example = "A区")
  62 + private String locationName;
  63 +
  64 + @Schema(description = "库位 ID", example = "1")
  65 + private Long areaId;
  66 +
  67 + @Schema(description = "库位名称", example = "A-01-01")
  68 + private String areaName;
  69 +
  70 + @Schema(description = "有效期")
  71 + private LocalDate expireDate;
  72 +
  73 + @Schema(description = "备注", example = "备注")
  74 + private String remark;
  75 +
  76 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  77 + private LocalDateTime createTime;
  78 +
  79 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/wmpackage/vo/line/MesWmPackageLineSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.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 +import java.time.LocalDate;
  10 +
  11 +@Schema(description = "管理后台 - MES 装箱明细新增/修改 Request VO")
  12 +@Data
  13 +public class MesWmPackageLineSaveReqVO {
  14 +
  15 + @Schema(description = "编号", example = "1024")
  16 + private Long id;
  17 +
  18 + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + @NotNull(message = "装箱单 ID 不能为空")
  20 + private Long packageId;
  21 +
  22 + @Schema(description = "库存记录 ID", example = "1")
  23 + private Long materialStockId;
  24 +
  25 + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  26 + @NotNull(message = "产品物料不能为空")
  27 + private Long itemId;
  28 +
  29 + @Schema(description = "装箱数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
  30 + @NotNull(message = "装箱数量不能为空")
  31 + @DecimalMin(value = "0.01", message = "装箱数量必须大于 0")
  32 + private BigDecimal quantity;
  33 +
  34 + @Schema(description = "生产工单 ID", example = "1")
  35 + private Long workOrderId;
  36 +
  37 + @Schema(description = "仓库 ID", example = "1")
  38 + private Long warehouseId;
  39 +
  40 + @Schema(description = "库区 ID", example = "1")
  41 + private Long locationId;
  42 +
  43 + @Schema(description = "库位 ID", example = "1")
  44 + private Long areaId;
  45 +
  46 + @Schema(description = "有效期")
  47 + private LocalDate expireDate;
  48 +
  49 + @Schema(description = "备注", example = "备注")
  50 + private String remark;
  51 +
  52 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/wmpackage/MesWmPackageDO.java 0 → 100644
  1 +// TODO @AI:报名改成 packages 避免 Java 关键字冲突;
  2 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage;
  3 +
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  7 +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
  8 +import com.baomidou.mybatisplus.annotation.KeySequence;
  9 +import com.baomidou.mybatisplus.annotation.TableId;
  10 +import com.baomidou.mybatisplus.annotation.TableName;
  11 +import lombok.*;
  12 +
  13 +import java.math.BigDecimal;
  14 +import java.time.LocalDate;
  15 +
  16 +/**
  17 + * MES 装箱单 DO
  18 + */
  19 +@TableName("mes_wm_package")
  20 +@KeySequence("mes_wm_package_seq")
  21 +@Data
  22 +@EqualsAndHashCode(callSuper = true)
  23 +@ToString(callSuper = true)
  24 +@Builder
  25 +@NoArgsConstructor
  26 +@AllArgsConstructor
  27 +public class MesWmPackageDO extends BaseDO {
  28 +
  29 + private static final Integer PARENT_ID_ROOT = 0;
  30 +
  31 + @TableId
  32 + private Long id;
  33 + /**
  34 + * 装箱单编号
  35 + */
  36 + private String code;
  37 + /**
  38 + * 父箱 ID
  39 + */
  40 + private Long parentId;
  41 + /**
  42 + * 装箱日期
  43 + */
  44 + private LocalDate packageDate;
  45 + // TODO @AI:改成 salesOrderCode
  46 + /**
  47 + * 销售订单编号
  48 + */
  49 + private String soCode;
  50 + /**
  51 + * 发票编号
  52 + */
  53 + private String invoiceCode;
  54 + /**
  55 + * 客户 ID
  56 + *
  57 + * 关联 {@link MesMdClientDO#getId()}
  58 + */
  59 + private Long clientId;
  60 + /**
  61 + * 箱长度
  62 + */
  63 + private BigDecimal length;
  64 + /**
  65 + * 箱宽度
  66 + */
  67 + private BigDecimal width;
  68 + /**
  69 + * 箱高度
  70 + */
  71 + private BigDecimal height;
  72 + /**
  73 + * 尺寸单位 ID
  74 + *
  75 + * 关联 {@link MesMdUnitMeasureDO#getId()}
  76 + */
  77 + private Long sizeUnitId;
  78 + /**
  79 + * 净重
  80 + */
  81 + private BigDecimal netWeight;
  82 + /**
  83 + * 毛重
  84 + */
  85 + private BigDecimal grossWeight;
  86 + /**
  87 + * 重量单位 ID
  88 + *
  89 + * 关联 {@link MesMdUnitMeasureDO#getId()}
  90 + */
  91 + private Long weightUnitId;
  92 + /**
  93 + * 检查员用户 ID
  94 + *
  95 + * 关联 AdminUserDO 的 id
  96 + */
  97 + private Long inspectorUserId;
  98 + // TODO @AI:自定义一个属于自己的枚举类;类似:MesWmSalesNoticeStatusEnum
  99 + /**
  100 + * 状态
  101 + *
  102 + * 枚举 {@link MesOrderStatusConstants#PREPARE}、{@link MesOrderStatusConstants#FINISHED}
  103 + */
  104 + private Integer status;
  105 + /**
  106 + * 备注
  107 + */
  108 + private String remark;
  109 +
  110 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/wmpackage/MesWmPackageLineDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage;
  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.pro.workorder.MesProWorkOrderDO;
  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 cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
  9 +import com.baomidou.mybatisplus.annotation.KeySequence;
  10 +import com.baomidou.mybatisplus.annotation.TableId;
  11 +import com.baomidou.mybatisplus.annotation.TableName;
  12 +import lombok.*;
  13 +
  14 +import java.math.BigDecimal;
  15 +import java.time.LocalDate;
  16 +
  17 +/**
  18 + * MES 装箱明细 DO
  19 + */
  20 +@TableName("mes_wm_package_line")
  21 +@KeySequence("mes_wm_package_line_seq")
  22 +@Data
  23 +@EqualsAndHashCode(callSuper = true)
  24 +@ToString(callSuper = true)
  25 +@Builder
  26 +@NoArgsConstructor
  27 +@AllArgsConstructor
  28 +public class MesWmPackageLineDO extends BaseDO {
  29 +
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 装箱单 ID
  34 + *
  35 + * 关联 {@link MesWmPackageDO#getId()}
  36 + */
  37 + private Long packageId;
  38 + /**
  39 + * 库存记录 ID
  40 + */
  41 + private Long materialStockId;
  42 + /**
  43 + * 产品物料 ID
  44 + *
  45 + * 关联 {@link MesMdItemDO#getId()}
  46 + */
  47 + private Long itemId;
  48 + /**
  49 + * 装箱数量
  50 + */
  51 + private BigDecimal quantity;
  52 + // TODO @AI:需要在确认下;
  53 + /**
  54 + * 生产工单 ID
  55 + *
  56 + * 关联 {@link MesProWorkOrderDO#getId()}
  57 + */
  58 + private Long workOrderId;
  59 + /**
  60 + * 仓库 ID
  61 + *
  62 + * 关联 {@link MesWmWarehouseDO#getId()}
  63 + */
  64 + private Long warehouseId;
  65 + /**
  66 + * 库区 ID
  67 + *
  68 + * 关联 {@link MesWmWarehouseLocationDO#getId()}
  69 + */
  70 + private Long locationId;
  71 + /**
  72 + * 库位 ID
  73 + *
  74 + * 关联 {@link MesWmWarehouseAreaDO#getId()}
  75 + */
  76 + private Long areaId;
  77 + /**
  78 + * 有效期
  79 + */
  80 + private LocalDate expireDate;
  81 + /**
  82 + * 备注
  83 + */
  84 + private String remark;
  85 +
  86 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/wmpackage/MesWmPackageLineMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.wmpackage;
  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.wmpackage.vo.line.MesWmPackageLinePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageLineDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +@Mapper
  13 +public interface MesWmPackageLineMapper extends BaseMapperX<MesWmPackageLineDO> {
  14 +
  15 + default PageResult<MesWmPackageLineDO> selectPage(MesWmPackageLinePageReqVO reqVO) {
  16 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmPackageLineDO>()
  17 + .eqIfPresent(MesWmPackageLineDO::getPackageId, reqVO.getPackageId())
  18 + .orderByDesc(MesWmPackageLineDO::getId));
  19 + }
  20 +
  21 + default List<MesWmPackageLineDO> selectListByPackageId(Long packageId) {
  22 + return selectList(MesWmPackageLineDO::getPackageId, packageId);
  23 + }
  24 +
  25 + default void deleteByPackageId(Long packageId) {
  26 + delete(MesWmPackageLineDO::getPackageId, packageId);
  27 + }
  28 +
  29 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/wmpackage/MesWmPackageMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.wm.wmpackage;
  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.wmpackage.vo.MesWmPackagePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +import java.util.List;
  11 +
  12 +@Mapper
  13 +public interface MesWmPackageMapper extends BaseMapperX<MesWmPackageDO> {
  14 +
  15 + default PageResult<MesWmPackageDO> selectPage(MesWmPackagePageReqVO reqVO) {
  16 + return selectPage(reqVO, new LambdaQueryWrapperX<MesWmPackageDO>()
  17 + .likeIfPresent(MesWmPackageDO::getCode, reqVO.getCode())
  18 + .likeIfPresent(MesWmPackageDO::getSoCode, reqVO.getSoCode())
  19 + .eqIfPresent(MesWmPackageDO::getClientId, reqVO.getClientId())
  20 + .betweenIfPresent(MesWmPackageDO::getPackageDate, reqVO.getPackageDate())
  21 + .eqIfPresent(MesWmPackageDO::getStatus, reqVO.getStatus())
  22 + .orderByDesc(MesWmPackageDO::getId));
  23 + }
  24 +
  25 + default MesWmPackageDO selectByCode(String code) {
  26 + return selectOne(MesWmPackageDO::getCode, code);
  27 + }
  28 +
  29 + default List<MesWmPackageDO> selectListByParentId(Long parentId) {
  30 + return selectList(MesWmPackageDO::getParentId, parentId);
  31 + }
  32 +
  33 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -351,8 +351,10 @@ public interface ErrorCodeConstants {
351 351 ErrorCode WM_ITEM_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_705_005, "入库单状态不正确");
352 352 ErrorCode WM_ITEM_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_705_006, "已完成或已取消的入库单不允许取消");
353 353 ErrorCode WM_ITEM_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_705_100, "采购入库单行不存在");
354   - ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_REQUIRED = new ErrorCode(1_040_705_101, "入库单关联了到货通知单,必须选择到货通知单行");
355   - ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_NOT_ALLOWED = new ErrorCode(1_040_705_102, "入库单未关联到货通知单,不能选择到货通知单行");
  354 + ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_REQUIRED = new ErrorCode(1_040_705_101,
  355 + "入库单关联了到货通知单,必须选择到货通知单行");
  356 + ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_NOT_ALLOWED = new ErrorCode(1_040_705_102,
  357 + "入库单未关联到货通知单,不能选择到货通知单行");
356 358 ErrorCode WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_705_200, "采购入库明细不存在");
357 359  
358 360 // ========== MES 仓库管理-领料申请单(1-040-706-000) ==========
... ... @@ -509,4 +511,12 @@ public interface ErrorCodeConstants {
509 511 ErrorCode BARCODE_BIZ_CODE_NOT_EXISTS = new ErrorCode(1_040_731_004, "业务编码不能为空");
510 512 ErrorCode BARCODE_CONFIG_NOT_EXISTS = new ErrorCode(1_040_731_005, "条码配置不存在");
511 513  
  514 + // ========== MES 仓库管理-装箱单(1-040-740-000) ==========
  515 + ErrorCode WM_PACKAGE_NOT_EXISTS = new ErrorCode(1_040_740_000, "装箱单不存在");
  516 + ErrorCode WM_PACKAGE_CODE_DUPLICATE = new ErrorCode(1_040_740_001, "装箱单编码已存在");
  517 + ErrorCode WM_PACKAGE_STATUS_NOT_PREPARE = new ErrorCode(1_040_740_002, "只有草稿状态才允许此操作");
  518 + ErrorCode WM_PACKAGE_PARENT_NOT_EXISTS = new ErrorCode(1_040_740_003, "父箱不存在");
  519 + ErrorCode WM_PACKAGE_PARENT_SELF = new ErrorCode(1_040_740_004, "不能选择自己作为父箱");
  520 + ErrorCode WM_PACKAGE_LINE_NOT_EXISTS = new ErrorCode(1_040_740_100, "装箱明细不存在");
  521 +
512 522 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/wmpackage/MesWmPackageLineService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.wmpackage;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLinePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLineSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageLineDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * MES 装箱明细 Service 接口
  13 + */
  14 +public interface MesWmPackageLineService {
  15 +
  16 + /**
  17 + * 创建装箱明细
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createPackageLine(@Valid MesWmPackageLineSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 修改装箱明细
  26 + *
  27 + * @param updateReqVO 修改信息
  28 + */
  29 + void updatePackageLine(@Valid MesWmPackageLineSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除装箱明细
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deletePackageLine(Long id);
  37 +
  38 + /**
  39 + * 获得装箱明细
  40 + *
  41 + * @param id 编号
  42 + * @return 装箱明细
  43 + */
  44 + MesWmPackageLineDO getPackageLine(Long id);
  45 +
  46 + /**
  47 + * 获得装箱明细分页
  48 + *
  49 + * @param pageReqVO 分页查询
  50 + * @return 分页结果
  51 + */
  52 + PageResult<MesWmPackageLineDO> getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO);
  53 +
  54 + /**
  55 + * 根据装箱单 ID 获得明细列表
  56 + *
  57 + * @param packageId 装箱单 ID
  58 + * @return 明细列表
  59 + */
  60 + List<MesWmPackageLineDO> getPackageLineListByPackageId(Long packageId);
  61 +
  62 + /**
  63 + * 根据装箱单 ID 删除所有明细
  64 + *
  65 + * @param packageId 装箱单 ID
  66 + */
  67 + void deletePackageLineByPackageId(Long packageId);
  68 +
  69 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/wmpackage/MesWmPackageLineServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.wmpackage;
  2 +
  3 +import cn.hutool.core.util.ObjUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLinePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.line.MesWmPackageLineSaveReqVO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageDO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageLineDO;
  10 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.wmpackage.MesWmPackageLineMapper;
  11 +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
  12 +import jakarta.annotation.Resource;
  13 +import org.springframework.context.annotation.Lazy;
  14 +import org.springframework.stereotype.Service;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  21 +
  22 +@Service
  23 +@Validated
  24 +public class MesWmPackageLineServiceImpl implements MesWmPackageLineService {
  25 +
  26 + @Resource
  27 + private MesWmPackageLineMapper packageLineMapper;
  28 + @Resource
  29 + @Lazy
  30 + private MesWmPackageService packageService;
  31 +
  32 + @Override
  33 + public Long createPackageLine(MesWmPackageLineSaveReqVO createReqVO) {
  34 + // TODO @AI:检查关联的 packageId(草稿)、itemId
  35 +
  36 + // 校验装箱单状态为草稿
  37 + validatePackageStatusDraft(createReqVO.getPackageId());
  38 + MesWmPackageLineDO line = BeanUtils.toBean(createReqVO, MesWmPackageLineDO.class);
  39 + packageLineMapper.insert(line);
  40 + return line.getId();
  41 + }
  42 +
  43 + @Override
  44 + public void updatePackageLine(MesWmPackageLineSaveReqVO updateReqVO) {
  45 + // 校验存在
  46 + MesWmPackageLineDO line = validatePackageLineExists(updateReqVO.getId());
  47 + // TODO @AI:检查关联的 packageId(草稿)、itemId
  48 +
  49 + // 校验装箱单状态为草稿
  50 + validatePackageStatusDraft(line.getPackageId());
  51 + MesWmPackageLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageLineDO.class);
  52 + packageLineMapper.updateById(updateObj);
  53 + }
  54 +
  55 + @Override
  56 + public void deletePackageLine(Long id) {
  57 + // 校验存在
  58 + MesWmPackageLineDO line = validatePackageLineExists(id);
  59 + // 校验装箱单状态为草稿
  60 + validatePackageStatusDraft(line.getPackageId());
  61 +
  62 + // 删除
  63 + packageLineMapper.deleteById(id);
  64 + }
  65 +
  66 + @Override
  67 + public MesWmPackageLineDO getPackageLine(Long id) {
  68 + return packageLineMapper.selectById(id);
  69 + }
  70 +
  71 + @Override
  72 + public PageResult<MesWmPackageLineDO> getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO) {
  73 + return packageLineMapper.selectPage(pageReqVO);
  74 + }
  75 +
  76 + @Override
  77 + public List<MesWmPackageLineDO> getPackageLineListByPackageId(Long packageId) {
  78 + return packageLineMapper.selectListByPackageId(packageId);
  79 + }
  80 +
  81 + @Override
  82 + public void deletePackageLineByPackageId(Long packageId) {
  83 + packageLineMapper.deleteByPackageId(packageId);
  84 + }
  85 +
  86 + // ========== 校验方法 ==========
  87 +
  88 + private MesWmPackageLineDO validatePackageLineExists(Long id) {
  89 + MesWmPackageLineDO line = packageLineMapper.selectById(id);
  90 + if (line == null) {
  91 + throw exception(WM_PACKAGE_LINE_NOT_EXISTS);
  92 + }
  93 + return line;
  94 + }
  95 +
  96 + // TODO @AI:这个方法,应该 packageService 实现;
  97 + private void validatePackageStatusDraft(Long packageId) {
  98 + MesWmPackageDO packageDO = packageService.getPackage(packageId);
  99 + if (packageDO == null) {
  100 + throw exception(WM_PACKAGE_NOT_EXISTS);
  101 + }
  102 + if (ObjUtil.notEqual(MesOrderStatusConstants.PREPARE, packageDO.getStatus())) {
  103 + throw exception(WM_PACKAGE_STATUS_NOT_PREPARE);
  104 + }
  105 + }
  106 +
  107 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/wmpackage/MesWmPackageService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.wmpackage;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackagePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackageSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * MES 装箱单 Service 接口
  13 + */
  14 +public interface MesWmPackageService {
  15 +
  16 + /**
  17 + * 创建装箱单
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createPackage(@Valid MesWmPackageSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 修改装箱单
  26 + *
  27 + * @param updateReqVO 修改信息
  28 + */
  29 + void updatePackage(@Valid MesWmPackageSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除装箱单
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deletePackage(Long id);
  37 +
  38 + /**
  39 + * 获得装箱单
  40 + *
  41 + * @param id 编号
  42 + * @return 装箱单
  43 + */
  44 + MesWmPackageDO getPackage(Long id);
  45 +
  46 + /**
  47 + * 获得装箱单分页
  48 + *
  49 + * @param pageReqVO 分页查询
  50 + * @return 分页结果
  51 + */
  52 + PageResult<MesWmPackageDO> getPackagePage(MesWmPackagePageReqVO pageReqVO);
  53 +
  54 + /**
  55 + * 完成装箱单
  56 + *
  57 + * @param id 编号
  58 + */
  59 + void finishPackage(Long id);
  60 +
  61 + /**
  62 + * 获得装箱单树形结构
  63 + *
  64 + * @return 装箱单列表(树形)
  65 + */
  66 + List<MesWmPackageDO> getPackageTree();
  67 +
  68 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/wmpackage/MesWmPackageServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.wm.wmpackage;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackagePageReqVO;
  8 +import cn.iocoder.yudao.module.mes.controller.admin.wm.wmpackage.vo.MesWmPackageSaveReqVO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.wmpackage.MesWmPackageDO;
  10 +import cn.iocoder.yudao.module.mes.dal.mysql.wm.wmpackage.MesWmPackageMapper;
  11 +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants;
  12 +import jakarta.annotation.Resource;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.transaction.annotation.Transactional;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  21 +
  22 +@Service
  23 +@Validated
  24 +public class MesWmPackageServiceImpl implements MesWmPackageService {
  25 +
  26 + @Resource
  27 + private MesWmPackageMapper packageMapper;
  28 + @Resource
  29 + private MesWmPackageLineService packageLineService;
  30 +
  31 + @Override
  32 + public Long createPackage(MesWmPackageSaveReqVO createReqVO) {
  33 + // 校验编码唯一性
  34 + validateCodeUnique(null, createReqVO.getCode());
  35 + // 校验父箱存在
  36 + validateParentExists(createReqVO.getParentId());
  37 +
  38 + // 创建装箱单,默认为草稿状态
  39 + MesWmPackageDO packageDO = BeanUtils.toBean(createReqVO, MesWmPackageDO.class);
  40 + packageDO.setStatus(MesOrderStatusConstants.PREPARE);
  41 + if (packageDO.getParentId() == null) {
  42 + packageDO.setParentId(0L);
  43 + }
  44 + packageMapper.insert(packageDO);
  45 + return packageDO.getId();
  46 + }
  47 +
  48 + @Override
  49 + public void updatePackage(MesWmPackageSaveReqVO updateReqVO) {
  50 + // 校验存在且为草稿
  51 + validatePackageExistsAndDraft(updateReqVO.getId());
  52 + // 校验编码唯一性
  53 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
  54 + // TODO @AI:是不是创建一个方法,校验 parent;因为 create 和 update 都需要;
  55 + // 校验父箱存在,且不能选自己或子节点
  56 + validateParentExists(updateReqVO.getParentId());
  57 + if (updateReqVO.getParentId() != null && ObjUtil.equal(updateReqVO.getParentId(), updateReqVO.getId())) {
  58 + throw exception(WM_PACKAGE_PARENT_SELF);
  59 + }
  60 +
  61 + // 更新装箱单
  62 + MesWmPackageDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageDO.class);
  63 + packageMapper.updateById(updateObj);
  64 + }
  65 +
  66 + @Override
  67 + @Transactional(rollbackFor = Exception.class)
  68 + public void deletePackage(Long id) {
  69 + // 校验存在且为草稿
  70 + validatePackageExistsAndDraft(id);
  71 +
  72 + // 删除装箱明细
  73 + packageLineService.deletePackageLineByPackageId(id);
  74 + // 删除装箱单
  75 + packageMapper.deleteById(id);
  76 +
  77 + // 级联删除子箱
  78 + List<MesWmPackageDO> children = packageMapper.selectListByParentId(id);
  79 + if (CollUtil.isNotEmpty(children)) {
  80 + for (MesWmPackageDO child : children) {
  81 + deletePackage(child.getId());
  82 + }
  83 + }
  84 + }
  85 +
  86 + @Override
  87 + public MesWmPackageDO getPackage(Long id) {
  88 + return packageMapper.selectById(id);
  89 + }
  90 +
  91 + @Override
  92 + public PageResult<MesWmPackageDO> getPackagePage(MesWmPackagePageReqVO pageReqVO) {
  93 + return packageMapper.selectPage(pageReqVO);
  94 + }
  95 +
  96 + @Override
  97 + public void finishPackage(Long id) {
  98 + // 校验存在且为草稿
  99 + validatePackageExistsAndDraft(id);
  100 +
  101 + // 更新状态为已完成
  102 + packageMapper.updateById(new MesWmPackageDO()
  103 + .setId(id).setStatus(MesOrderStatusConstants.FINISHED));
  104 + }
  105 +
  106 + @Override
  107 + public List<MesWmPackageDO> getPackageTree() {
  108 + return packageMapper.selectList();
  109 + }
  110 +
  111 + // ========== 校验方法 ==========
  112 +
  113 + private MesWmPackageDO validatePackageExists(Long id) {
  114 + MesWmPackageDO packageDO = packageMapper.selectById(id);
  115 + if (packageDO == null) {
  116 + throw exception(WM_PACKAGE_NOT_EXISTS);
  117 + }
  118 + return packageDO;
  119 + }
  120 +
  121 + private MesWmPackageDO validatePackageExistsAndDraft(Long id) {
  122 + MesWmPackageDO packageDO = validatePackageExists(id);
  123 + if (ObjUtil.notEqual(MesOrderStatusConstants.PREPARE, packageDO.getStatus())) {
  124 + throw exception(WM_PACKAGE_STATUS_NOT_PREPARE);
  125 + }
  126 + return packageDO;
  127 + }
  128 +
  129 + private void validateCodeUnique(Long id, String code) {
  130 + MesWmPackageDO packageDO = packageMapper.selectByCode(code);
  131 + if (packageDO == null) {
  132 + return;
  133 + }
  134 + if (ObjUtil.notEqual(id, packageDO.getId())) {
  135 + throw exception(WM_PACKAGE_CODE_DUPLICATE);
  136 + }
  137 + }
  138 +
  139 + private void validateParentExists(Long parentId) {
  140 + if (parentId == null || parentId == 0L) {
  141 + return;
  142 + }
  143 + MesWmPackageDO parent = packageMapper.selectById(parentId);
  144 + if (parent == null) {
  145 + throw exception(WM_PACKAGE_PARENT_NOT_EXISTS);
  146 + }
  147 + }
  148 +
  149 +}
... ...