Commit 05ec61e6de5afc124e1b3827b2ce6de98c64c7f8

Authored by YunaiV
1 parent 97e55806

✨ feat(mes): 添加到货通知单精简列表接口及状态筛选功能

新增获取到货通知单的精简列表接口,支持按状态筛选。更新相关状态枚举和校验逻辑,优化采购入库单的审批和取消功能,确保系统在处理入库单时的状态管理更加清晰和高效。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java
... ... @@ -121,6 +121,15 @@ public class MesWmArrivalNoticeController {
121 121 return success(true);
122 122 }
123 123  
  124 + @GetMapping("/simple-list")
  125 + @Operation(summary = "获得到货通知单精简列表")
  126 + @Parameter(name = "status", description = "状态", example = "2")
  127 + public CommonResult<List<MesWmArrivalNoticeRespVO>> getArrivalNoticeSimpleList(
  128 + @RequestParam(value = "status", required = false) Integer status) {
  129 + List<MesWmArrivalNoticeDO> list = arrivalNoticeService.getArrivalNoticeListByStatus(status);
  130 + return success(buildRespVOList(list));
  131 + }
  132 +
124 133 // ==================== 拼接 VO ====================
125 134  
126 135 private List<MesWmArrivalNoticeRespVO> buildRespVOList(List<MesWmArrivalNoticeDO> list) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptController.java
... ... @@ -137,12 +137,13 @@ public class MesWmItemReceiptController {
137 137 return success(true);
138 138 }
139 139  
140   - @PutMapping("/approve")
141   - @Operation(summary = "审批采购入库单")
  140 + // TODO @芋艿:【待定,不要删除】这个是合适的单词么?
  141 + @PutMapping("/shelving")
  142 + @Operation(summary = "执行上架")
142 143 @Parameter(name = "id", description = "编号", required = true)
143 144 @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')")
144   - public CommonResult<Boolean> approveItemReceipt(@RequestParam("id") Long id) {
145   - itemReceiptService.approveItemReceipt(id);
  145 + public CommonResult<Boolean> shelvingItemReceipt(@RequestParam("id") Long id) {
  146 + itemReceiptService.shelvingItemReceipt(id);
146 147 return success(true);
147 148 }
148 149  
... ... @@ -155,6 +156,15 @@ public class MesWmItemReceiptController {
155 156 return success(true);
156 157 }
157 158  
  159 + @PutMapping("/cancel")
  160 + @Operation(summary = "取消采购入库单")
  161 + @Parameter(name = "id", description = "编号", required = true)
  162 + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')")
  163 + public CommonResult<Boolean> cancelItemReceipt(@RequestParam("id") Long id) {
  164 + itemReceiptService.cancelItemReceipt(id);
  165 + return success(true);
  166 + }
  167 +
158 168 // ==================== 拼接 VO ====================
159 169  
160 170 private List<MesWmItemReceiptRespVO> buildRespVOList(List<MesWmItemReceiptDO> list) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
... ... @@ -53,6 +53,7 @@ public class MesWmItemReceiptDO extends BaseDO {
53 53 * 关联 {@link MesWmArrivalNoticeDO#getId()}
54 54 */
55 55 private Long noticeId;
  56 + // TODO @AI:不用存储,它冗余自 noticeId 订单,可以需要的时候去读取!
56 57 /**
57 58 * 采购订单编号
58 59 */
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -322,8 +322,8 @@ public interface ErrorCodeConstants {
322 322 ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在");
323 323 ErrorCode WM_ARRIVAL_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_704_001, "到货通知单编码已存在");
324 324 ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE = new ErrorCode(1_040_704_002, "只有草稿状态才允许此操作");
325   - ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_SUBMITTED = new ErrorCode(1_040_704_003, "只有已提交状态才允许审批");
326   - ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_APPROVED = new ErrorCode(1_040_704_004, "只有已审批状态才允许完成");
  325 + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC = new ErrorCode(1_040_704_003, "只有待质检状态才允许审批");
  326 + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT = new ErrorCode(1_040_704_004, "只有待入库状态才允许完成");
327 327 ErrorCode WM_ARRIVAL_NOTICE_IQC_PENDING = new ErrorCode(1_040_704_005, "存在待检验行,无法审批通过");
328 328 ErrorCode WM_ARRIVAL_NOTICE_NO_LINE = new ErrorCode(1_040_704_006, "至少需要一条行项目");
329 329 ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_704_100, "到货通知单行不存在");
... ... @@ -331,10 +331,11 @@ public interface ErrorCodeConstants {
331 331 // ========== MES 仓库管理-采购入库单(1-040-705-000) ==========
332 332 ErrorCode WM_ITEM_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_705_000, "采购入库单不存在");
333 333 ErrorCode WM_ITEM_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_705_001, "采购入库单编码已存在");
334   - ErrorCode WM_ITEM_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_705_002, "只有草稿状态才允许此操作");
  334 + ErrorCode WM_ITEM_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_705_002, "只有草稿或待上架状态才允许此操作");
335 335 ErrorCode WM_ITEM_RECEIPT_NO_LINE = new ErrorCode(1_040_705_003, "至少需要一条行项目");
336 336 ErrorCode WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_705_004, "明细上架总数与行入库数量不匹配");
337 337 ErrorCode WM_ITEM_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_705_005, "入库单状态不正确");
  338 + ErrorCode WM_ITEM_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_705_006, "已完成或已取消的入库单不允许取消");
338 339 ErrorCode WM_ITEM_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_705_100, "采购入库单行不存在");
339 340 ErrorCode WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_705_200, "采购入库明细不存在");
340 341  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java
... ... @@ -16,8 +16,8 @@ import java.util.Arrays;
16 16 public enum MesWmArrivalNoticeStatusEnum implements ArrayValuable<Integer> {
17 17  
18 18 PREPARE(0, "草稿"),
19   - SUBMITTED(1, "已提交"),
20   - APPROVED(2, "已审批"),
  19 + PENDING_QC(1, "待质检"),
  20 + PENDING_RECEIPT(2, "待入库"),
21 21 FINISHED(3, "已完成");
22 22  
23 23 public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmArrivalNoticeStatusEnum::getStatus).toArray(Integer[]::new);
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemReceiptStatusEnum.java
... ... @@ -16,9 +16,10 @@ import java.util.Arrays;
16 16 public enum MesWmItemReceiptStatusEnum implements ArrayValuable<Integer> {
17 17  
18 18 PREPARE(0, "草稿"),
19   - SUBMITTED(1, "已提交"),
20   - APPROVED(2, "已审批"),
21   - FINISHED(3, "已完成");
  19 + APPROVING(1, "待上架"),
  20 + APPROVED(2, "待入库"),
  21 + FINISHED(3, "已完成"),
  22 + CANCELED(4, "已取消");
22 23  
23 24 public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmItemReceiptStatusEnum::getStatus).toArray(Integer[]::new);
24 25  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java
... ... @@ -56,21 +56,21 @@ public interface MesWmArrivalNoticeService {
56 56 PageResult<MesWmArrivalNoticeDO> getArrivalNoticePage(MesWmArrivalNoticePageReqVO pageReqVO);
57 57  
58 58 /**
59   - * 提交到货通知单(草稿 → 已提交)
  59 + * 提交到货通知单(草稿 → 待质检/待入库)
60 60 *
61 61 * @param id 编号
62 62 */
63 63 void submitArrivalNotice(Long id);
64 64  
65 65 /**
66   - * 审批到货通知单(已提交 → 已审批)
  66 + * 审批到货通知单(待质检 → 待入库)
67 67 *
68 68 * @param id 编号
69 69 */
70 70 void approveArrivalNotice(Long id);
71 71  
72 72 /**
73   - * 完成到货通知单(已审批 → 已完成),内部调用
  73 + * 完成到货通知单(待入库 → 已完成),内部调用
74 74 *
75 75 * @param id 编号
76 76 */
... ... @@ -88,4 +88,12 @@ public interface MesWmArrivalNoticeService {
88 88 return convertMap(getArrivalNoticeList(ids), MesWmArrivalNoticeDO::getId);
89 89 }
90 90  
  91 + /**
  92 + * 按状态获得到货通知单列表
  93 + *
  94 + * @param status 状态
  95 + * @return 到货通知单列表
  96 + */
  97 + List<MesWmArrivalNoticeDO> getArrivalNoticeListByStatus(Integer status);
  98 +
91 99 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java
... ... @@ -96,13 +96,13 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
96 96 // 检查所有行的 iqcCheckFlag:如果没有需要检验的行,则直接审批通过
97 97 boolean needCheck = CollectionUtils.anyMatch(lines, line -> Boolean.TRUE.equals(line.getIqcCheckFlag()));
98 98 if (!needCheck) {
99   - // 不需要检验,直接审批通过
  99 + // 不需要检验,直接进入待入库
100 100 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
101   - .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus()));
  101 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus()));
102 102 } else {
103   - // 需要检验,提交待审批
  103 + // 需要检验,进入待质检
104 104 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
105   - .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.SUBMITTED.getStatus()));
  105 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()));
106 106 }
107 107 }
108 108  
... ... @@ -111,9 +111,9 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
111 111 public void approveArrivalNotice(Long id) {
112 112 // 校验存在
113 113 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
114   - // 校验状态:只有已提交才允许审批
115   - if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.SUBMITTED.getStatus(), notice.getStatus())) {
116   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_SUBMITTED);
  114 + // 校验状态:只有待质检才允许审批
  115 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), notice.getStatus())) {
  116 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC);
117 117 }
118 118  
119 119 // 校验所有 iqcCheckFlag=true 的行必须 iqcId 不为空
... ... @@ -125,16 +125,16 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
125 125 }
126 126 // 审批通过
127 127 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
128   - .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus()));
  128 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus()));
129 129 }
130 130  
131 131 @Override
132 132 public void finishArrivalNotice(Long id) {
133 133 // 校验存在
134 134 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
135   - // 校验状态:只有已审批才允许完成
136   - if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus(), notice.getStatus())) {
137   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_APPROVED);
  135 + // 校验状态:只有待入库才允许完成
  136 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), notice.getStatus())) {
  137 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT);
138 138 }
139 139  
140 140 // 完成
... ... @@ -150,6 +150,15 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
150 150 return arrivalNoticeMapper.selectByIds(ids);
151 151 }
152 152  
  153 + @Override
  154 + public List<MesWmArrivalNoticeDO> getArrivalNoticeListByStatus(Integer status) {
  155 + // TODO @AI:通过 selectListByStatus 方法实现,更通用;
  156 + if (status == null) {
  157 + return arrivalNoticeMapper.selectList();
  158 + }
  159 + return arrivalNoticeMapper.selectList(MesWmArrivalNoticeDO::getStatus, status);
  160 + }
  161 +
153 162 private MesWmArrivalNoticeDO validateArrivalNoticeExists(Long id) {
154 163 MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectById(id);
155 164 if (notice == null) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailServiceImpl.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.service.wm.itemreceipt;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
5 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailPageReqVO;
6 7 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO;
7 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
... ... @@ -36,7 +37,7 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
36 37 @Override
37 38 public Long createItemReceiptDetail(MesWmItemReceiptDetailSaveReqVO createReqVO) {
38 39 // 校验父单据存在且为草稿状态
39   - validateReceiptStatusDraft(createReqVO.getReceiptId());
  40 + validateReceiptStatusForDetailEdit(createReqVO.getReceiptId());
40 41  
41 42 MesWmItemReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmItemReceiptDetailDO.class);
42 43 itemReceiptDetailMapper.insert(detail);
... ... @@ -48,7 +49,7 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
48 49 // 校验存在
49 50 MesWmItemReceiptDetailDO detail = validateItemReceiptDetailExists(updateReqVO.getId());
50 51 // 校验父单据存在且为草稿状态
51   - validateReceiptStatusDraft(detail.getReceiptId());
  52 + validateReceiptStatusForDetailEdit(detail.getReceiptId());
52 53  
53 54 // 更新
54 55 MesWmItemReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptDetailDO.class);
... ... @@ -101,15 +102,18 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
101 102 return detail;
102 103 }
103 104  
  105 + // TODO @AI:在 itemReceiptService 里,封装一个这个方法;最好不要是 fordetail,而不是 prepare + approving 状态;
104 106 /**
105   - * 校验父采购入库单存在且为草稿状态
  107 + * 校验父采购入库单存在且允许编辑明细(草稿或待上架状态)
106 108 */
107   - private void validateReceiptStatusDraft(Long receiptId) {
  109 + private void validateReceiptStatusForDetailEdit(Long receiptId) {
108 110 MesWmItemReceiptDO receipt = itemReceiptService.getItemReceipt(receiptId);
109 111 if (receipt == null) {
110 112 throw exception(WM_ITEM_RECEIPT_NOT_EXISTS);
111 113 }
112   - if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) {
  114 + // TODO @AI:在 ObjectUtils 里,封装一个 notEquals 方法,简化代码;
  115 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())
  116 + && ObjUtil.notEqual(MesWmItemReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) {
113 117 throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
114 118 }
115 119 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java
... ... @@ -50,24 +50,31 @@ public interface MesWmItemReceiptService {
50 50 PageResult<MesWmItemReceiptDO> getItemReceiptPage(MesWmItemReceiptPageReqVO pageReqVO);
51 51  
52 52 /**
53   - * 提交采购入库单(草稿 → 已提交)
  53 + * 提交采购入库单(草稿 → 待上架)
54 54 *
55 55 * @param id 编号
56 56 */
57 57 void submitItemReceipt(Long id);
58 58  
59 59 /**
60   - * 审批采购入库单(已提交 → 已审批)
  60 + * 执行上架(待上架 → 待入库)
61 61 *
62 62 * @param id 编号
63 63 */
64   - void approveItemReceipt(Long id);
  64 + void shelvingItemReceipt(Long id);
65 65  
66 66 /**
67   - * 执行入库(已审批 → 已完成),更新库存台账
  67 + * 执行入库(待入库 → 已完成),更新库存台账
68 68 *
69 69 * @param id 编号
70 70 */
71 71 void executeItemReceipt(Long id);
72 72  
  73 + /**
  74 + * 取消采购入库单(任意非已完成/已取消状态 → 已取消)
  75 + *
  76 + * @param id 编号
  77 + */
  78 + void cancelItemReceipt(Long id);
  79 +
73 80 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
... ... @@ -107,17 +107,17 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
107 107 throw exception(WM_ITEM_RECEIPT_NO_LINE);
108 108 }
109 109  
110   - // 提交
  110 + // 提交(草稿 → 待上架)
111 111 itemReceiptMapper.updateById(new MesWmItemReceiptDO()
112   - .setId(id).setStatus(MesWmItemReceiptStatusEnum.SUBMITTED.getStatus()));
  112 + .setId(id).setStatus(MesWmItemReceiptStatusEnum.APPROVING.getStatus()));
113 113 }
114 114  
115 115 @Override
116 116 @Transactional(rollbackFor = Exception.class)
117   - public void approveItemReceipt(Long id) {
  117 + public void shelvingItemReceipt(Long id) {
118 118 // 校验存在
119 119 MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
120   - if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.SUBMITTED.getStatus(), receipt.getStatus())) {
  120 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) {
121 121 throw exception(WM_ITEM_RECEIPT_STATUS_ERROR);
122 122 }
123 123 // 校验每行的 SUM(detail.quantity) = line.receivedQuantity
... ... @@ -131,7 +131,7 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
131 131 }
132 132 }
133 133  
134   - // 审批
  134 + // 执行上架(待上架 → 待入库)
135 135 itemReceiptMapper.updateById(new MesWmItemReceiptDO()
136 136 .setId(id).setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus()));
137 137 }
... ... @@ -162,6 +162,23 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
162 162 }
163 163 }
164 164  
  165 + @Override
  166 + @Transactional(rollbackFor = Exception.class)
  167 + public void cancelItemReceipt(Long id) {
  168 + // 校验存在
  169 + MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
  170 + // 已完成和已取消不允许取消
  171 + // TODO @AI:在 ObjectUtils 里,有个 equalsAny;
  172 + // TODO @芋艿:【待确定】是不是就这 2 个状态了;
  173 + if (ObjUtil.equal(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), receipt.getStatus())
  174 + || ObjUtil.equal(MesWmItemReceiptStatusEnum.CANCELED.getStatus(), receipt.getStatus())) {
  175 + throw exception(WM_ITEM_RECEIPT_CANCEL_NOT_ALLOWED);
  176 + }
  177 + // 取消
  178 + itemReceiptMapper.updateById(new MesWmItemReceiptDO()
  179 + .setId(id).setStatus(MesWmItemReceiptStatusEnum.CANCELED.getStatus()));
  180 + }
  181 +
165 182 private MesWmItemReceiptDO validateItemReceiptExists(Long id) {
166 183 MesWmItemReceiptDO receipt = itemReceiptMapper.selectById(id);
167 184 if (receipt == null) {
... ...