docs/sale_return_from_outbound_and_no_qc.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,185 @@ # éå®éè´§æ¹é ï¼æéå®åºåºåéè´§ + åºåºæµéå»è´¨æ£ + æ¹æ¬¡ä¿ç ## ä¸ãéæ± | ç¼å· | éæ± | æ¥æº | |------|------|------| | E | éå®éè´§åæ¹ä¸ºãéæ©éå®åºåºååéè´§ãï¼ç©æãæ¹æ¬¡ãæ°éä¸éç±åºåºåå¸¦å ¥ | ç¨æ· | | F | åºåºæµé管çï¼éå®ä»åºï¼åè´§éç¥ / éå®åºåº / éå®éè´§ï¼ä¸éè¦è´¨æ£ | ç¨æ· | | G | éè´§å®æåå ¥åºï¼æ¹æ¬¡å·ä¸¢å¤± | ç¨æ·åé¦ | ä¸å¼ åæ®çèåå½å±ï¼`system_menu`ï¼ï¼ - ä»å¨ç©æµï¼5780ï¼ > éå®ä»åºï¼602479, path `sale`ï¼ - åè´§éç¥ï¼5867, `wls/salesnotice/index`ï¼ - éå®åºåºï¼5970, `wls/productsales/index`ï¼ - éå®éè´§ï¼5847, `wls/returnsales/index`ï¼ ## äºãç°ç¶ä¸æ ¹å ### 2.1 éè´§åä¸åºåºåæ å ³è - `mes_wm_return_sales` åªæ `sale_order_id` / `sale_order_code`ï¼ERP éå®è®¢åï¼å `after_sale_return_id`ï¼å®åéè´§ç³è¯·ï¼ï¼**没æéå®åºåºåå ³èåæ®µ**ã - `mes_wm_return_sales_line` åªæ `item_id` / `batch_id` / `batch_code`ï¼**没æåºåºåè¡å ³èåæ®µ**ã - éè´§è¡ç±å端æå·¥éæ©ç©æãæå·¥å¡«æ°éï¼ä¸ä¸ä»»ä½åºåºæ°æ®æ¯å¯¹ï¼æä»¥å¯è½éåºæªåºåºè¿çç©æã è¿ç«¯åº `mom-thzynew` å®é æ°æ®ï¼éè´§å 1 / éå®åºåºå 5ï¼ï¼ | åæ® | ç©æ | æ¹æ¬¡ | æ°é | |------|------|------|------| | éå®åºåºå 5080580566370931 | 114 | 4846066734735277 | 1 | | éå®éè´§å 0325446663418652ï¼å·²å®æï¼ | **116** | **空** | 1 | éè´§è¡éçæ¯å¦ä¸ä¸ªç©æï¼ä¸æ²¡æä»»ä½æ¹æ¬¡ââè¿æ£æ¯éæ± E å G çç°è±¡æ¥æºã ### 2.2 æ¹æ¬¡ä¸ºä»ä¹ä¸¢ 1. **éè´§è¡è¡¨åææ¹æ¬¡éæ©ç¦ç¨äº**ï¼`mom-pro2-before/src/views/wls/returnsales/data.ts` ä¸ `WmBatchSelect` åºå® `disabled: true`ï¼ç¨æ·æ ¹æ¬æ æ³éæ¹æ¬¡ï¼`batchId` æ°¸è¿ä¸ºç©ºã 2. **䏿¶æç»çæ¹æ¬¡æ¯æå¡«ææ¬æ¡**ï¼`useDetailFormSchema` åªæ `batchCode` è¾å ¥æ¡ï¼ä¸ä¸ä¼ä»éè´§è¡å¸¦å ¥ï¼ç¨æ·ä¸å¡«å°±ä¸ºç©ºã 3. **å端ä¸å åº**ï¼`MesWmReturnSalesDetailServiceImpl.fillBatchId` ä» å¨ `batchCode` é空æ¶åæ¥ `batchId`ï¼ä¸ºç©ºåè·³è¿ï¼`stockReturnSales` ç´æ¥ææç»ç `batchId/batchCode` åå ¥åºåäºå¡ï¼äºæ¯åºååæµæ°´é½æ²¡ææ¹æ¬¡ã 4. ç©æ 116 ç `is_batch_managed = 0`ï¼æä»¥ç°æãæ¹æ¬¡ç®¡çç©æå¿ é¡»éæ¹æ¬¡ãçæ ¡éªæ²¡ææ¦ä½ã ç»æï¼åºåäºå¡ 127ï¼`biz_type=120`ï¼`batch_id = NULL`ã`batch_code = ''`ï¼åºåç°æééä¹å°±æ²¡ææ¹æ¬¡ã ### 2.3 ç°æè´¨æ£é¾è·¯ - éè´§ï¼è¡å段 `rqc_check_flag` / `rqc_id` / `quality_status`ï¼æäº¤æ¶åå¨å¾ æ£è¡ â ç¶æ 1ï¼å¾ æ£éªï¼ï¼ç± RQC æ£éªå®ååå¹¶æåè¡ï¼`updateReturnSalesLineWhenRqcFinish`ï¼ï¼å ¨é¨æ£å®åè¿ 2ï¼å¾ æ§è¡ï¼ã - éå®åºåºï¼è¡å段 `oqc_check_flag` / `oqc_id` / `quality_status`ï¼æäº¤æ¶æè¡å建 OQCï¼`createOqcFromProductSales`ï¼ï¼æ OQC è¡ â 1ï¼å¾ æ£æµï¼ï¼æ£å®è¿ 2ï¼å¾ æ£è´§ï¼ï¼OQC ä¸åæ ¼ä¼ç´æ¥åæ¶åºåºåã - åè´§éç¥ï¼è¡å段 `oqc_check_flag`ï¼å建åºåºåæ¶å¤å¶å°åºåºè¡ã ## ä¸ãæ¹æ¡ ### 3.1 éæ± Eï¼æéå®åºåºåéè´§ #### 3.1.1 æ°æ®æ¨¡å 主表å¢å åºåºåå ³èï¼`product_sales_id` å½åä¸è¡¨å `mes_wm_product_sales` 对é½ï¼é¿å ä¸ `sale_order_id` æ··æ·ï¼ï¼ ```sql ALTER TABLE mes_wm_return_sales ADD COLUMN product_sales_id BIGINT NULL COMMENT 'éå®åºåºåç¼å·' AFTER sale_order_id, ADD COLUMN product_sales_code VARCHAR(100) NULL COMMENT 'éå®åºåºåå·ï¼åä½ï¼' AFTER product_sales_id; ALTER TABLE mes_wm_return_sales_line ADD COLUMN product_sales_line_id BIGINT NULL COMMENT 'éå®åºåºåè¡ç¼å·' AFTER return_id; CREATE INDEX idx_return_sales_product_sales ON mes_wm_return_sales(product_sales_id); CREATE INDEX idx_return_sales_line_product_sales_line ON mes_wm_return_sales_line(product_sales_line_id); ``` - `product_sales_id` å 许为空ï¼å®å模åéè¿ RPCï¼`MesWmReturnSalesApi.createReturnSales`ï¼å建çéè´§åæ²¡æåºåºåä¸ä¸æï¼å¿ 须继ç»å¯ç¨ã - 管çåå°æå·¥å建éè´§åæ¶**å¿ é¡»éæ©ä¸ä¸ªå·²å®æç¶æçéå®åºåºå**ï¼æ ¡éªå¨å端åï¼ã #### 3.1.2 å¯éæ°éå£å¾ ``` å¯éæ°é = åºåºè¡æ°é â Σ(该åºåºè¡å·²å ³èçææéè´§è¡æ°é) ææéè´§è¡ = æå±éè´§åæªå é¤ ä¸ ç¶æ â 已忶(5) ``` 注æï¼RQC æå产ççè¡ä¹è®¡å ¥ï¼æä»¥å£å¾å¤©ç¶è¦çãé¨ååæ ¼ãé¨åä¸åæ ¼ãçåå²åºæ¯ï¼å»è´¨æ£åä¸å产çæåï¼ã #### 3.1.3 æ°å¢æ¥å£ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/mes/wm/return-sales/returnable-product-sales/page` | å¯ééå®åºåºåå页ï¼ä» è¿åç¶æ=已宿(4) ä¸åå¨å¯éè¡>0 çåæ® | | GET | `/mes/wm/return-sales/returnable-product-sales/line-list` | æå®åºåºåçå¯éè¡å表ï¼å ¥å `salesId`ï¼ | å¯éè¡è¿ååæ®µï¼åºåºè¡ IDãç©æç¼ç /åç§°/è§æ ¼/åä½ãæ¹æ¬¡å·ãåºåºæ°éã已鿰éãå¯éæ°éã æéæ²¿ç¨ `mes:wm-return-sales:query`ã #### 3.1.4 ä¿åæ ¡éª å建/ä¿®æ¹éè´§åæ¶ï¼ 1. `product_sales_id` é空 â åºåºåå¿ é¡»åå¨ã`deleted=0`ãç¶æ = 已宿(4)ã 2. éè´§å `client_id` å¿ é¡»çäºåºåºå `client_id`ï¼åç«¯å¸¦å ¥å置为åªè¯»ï¼åç«¯å¼ºå¶æ ¡éªï¼ã 3. è¡ `product_sales_line_id` é空 â 该è¡å¿ é¡»å±äºæéåºåºåã 4. è¡ `item_id` / `batch_id` å¿ é¡»ä¸åºåºè¡ä¸è´ï¼æ°é `> 0` ä¸ `⤠å¯éæ°é`ï¼è®¡ç®æ¶æé¤å½åéè´§åèªèº«çè¡ï¼é¿å ç¼è¾æ¶èªæå ç¨ï¼ã 5. `product_sales_line_id` 为空çè¡ï¼ä» å®ååæ®ï¼æ²¿ç¨ç°ææå·¥æ ¡éªã æäº¤æ¶åæ´ä½å¤æ ¸ä¸æ¬¡å¯éæ°éï¼é²æ¢å¹¶ååæ®è¶ éã #### 3.1.5 å端交äºï¼ä¸æ¹å端ï¼ä» 说æï¼ - 表头ãéå®åºåºåãéæ©æ¡ï¼æå¼å¯éåå页弹çªï¼éä¸ååå¡«åºåºåå·ï¼å¹¶æå®¢æ·ç½®ä¸ºåªè¯»å¸¦å ¥ã - ç©æè¡æ¹ä¸ºãä»åºåºè¡éæ©ãï¼å¼¹çªååºå¯éè¡ï¼å¾éåå¸¦å ¥ç©æãæ¹æ¬¡ã`quantity` é»è®¤å¡«å¯éæ°éï¼è¡¨æ ¼å¢å ã已鿰é / å¯éæ°éã两åã - å 许é¨åéè´§ãå 许åä¸åºåºè¡å夿¬¡éè´§ï¼è·¨åæ®ï¼ã - 忢åºåºåæ¶æ¸ 空已添å çè¡ã ### 3.2 éæ± Fï¼åºåºæµéå»è´¨æ£ èå´å»ºè®®è¦çéå®ä»åºä¸å¼ åæ®ï¼åè´§éç¥ / éå®åºåº / éå®éè´§ï¼ï¼ä¸ãåºåºæµé管çãèåå£å¾ä¸è´ã | åæ® | 廿çå 容 | ç¶ææµè½¬åå | |------|-----------|-------------| | åè´§éç¥ | è¡ãæ¯å¦æ£éªãåæ®µä¸å | æ ï¼åæ¬ä¸å è´¨æ£æ¹ç¶æï¼ | | éå®åºåº | è¡ãæ¯å¦æ£éª / åºåæ£éªå / è´¨éç¶æããæäº¤æ¶èªå¨å建 OQCãOQC ååä¸ä¸åæ ¼åæ¶é»è¾ | æäº¤ï¼0 è稿 â 2 å¾ æ£è´§ï¼ä¸åç»è¿ 1 å¾ æ£æµï¼ | | éå®éè´§ | è¡ãæ¯å¦éè¦è´¨æ£ / éè´§æ£éªå / è´¨éç¶æããRQC åå䏿åè¡ãåè¡¨ãæ§è¡è´¨æ£ãæé® | æäº¤ï¼0 è稿 â 2 å¾ æ§è¡ï¼ä¸åç»è¿ 1 å¾ æ£éªï¼ | å¤çååï¼ - **æ°æ®åºåä¿çä¸å **ï¼æ 注åºå¼ï¼é¿å åå²åæ®ãæ¥è¡¨åå¤é¨æ¥å£ç´æ¥æ¥éï¼å¦åç»ç¡®è®¤å½»åºæ¸ çï¼ååç¬åºèæ¬ã - åå²åæ®ä¸å·²å¤äº 1ï¼å¾ æ£éª/å¾ æ£æµï¼çåæ®ï¼ä¿çç¶ææä¸¾ä¸é¡µé¢å±ç¤ºï¼æå·¥ãæ§è¡è´¨æ£ãå ¥å£ç§»é¤åéè¦äººå·¥æå¨éåæ®æ¨è¿æåæ¶ï¼ä¸çº¿åçç¹ä¸æ¬¡ï¼ã - 已产çç OQC/RQC æ£éªåä¸å é¤ï¼ä½ä¸ºåå²çæ¡£ï¼ä¸åæ°å»ºã - `MesQcSourceDocTypeEnum` ä¸ç `PRODUCT_SALES` / `RETURN_SALES` 忝ä¿çï¼å岿£éªå详æ ä»è¦è½æå¼æ¥æºåæ®ï¼ï¼ä½ä¸åææ°æ°æ®äº§çã ### 3.3 éæ± Gï¼æ¹æ¬¡ä¿ç 1. **éè´§è¡å è®¸éæ¹æ¬¡**ï¼è¡è¡¨å廿 `disabled: true`ï¼æç©æè¿æ»¤ `WmBatchSelect`ï¼éä¸åç¨æ¹æ¬¡ `code` åå¡« `batchCode`ã 2. **åç«¯è¡¥å ¨æ¹æ¬¡å·**ï¼è¡ä¿åæ¶è¥ `batchId` é空ã`batchCode` ä¸ºç©ºï¼æ `batchId` æ¥ `mes_wm_batch.code` åå¡«ï¼ä¿è¯è¡ä¸ä¸¤è ä¸è´ã 3. **䏿¶æç»ç»§æ¿è¡çæ¹æ¬¡**ï¼æç»è¡¨åçæ¹æ¬¡æ¹ä¸ºåªè¯»å±ç¤ºï¼å端ä¿åæç»æ¶**忽ç¥åç«¯ä¼ å ¥çæ¹æ¬¡**ï¼å¼ºå¶ `detail.batchId/batchCode = line.batchId/batchCode`ï¼ä»æ ¹ä¸æç»ä¸¢å¤±ã 4. **æ§è¡ä¸æ¶åç½®æ ¡éª**ï¼çæåºåäºå¡åæ ¡éªæ¯æ¡æç»çæ¹æ¬¡ä¸æå±è¡ä¸è´ï¼æ¹æ¬¡ç®¡çç©æå¿ é¡»é空ï¼ï¼ä¸ä¸è´ç´æ¥æ¥éå¹¶æåºç©æã 5. **å岿°æ®**ï¼éè´§å 1 çç©ææ¬èº«ééï¼åºåºæ¯ 114ï¼éè´§æ¯ 116ï¼ï¼å»ºè®®è¯¥åæ®åæ¶åææ°æµç¨éåï¼å¦ç¡®éä¿çï¼é人工æè¡/æç»æ¹åç©æ 114 + æ¹æ¬¡ 4846066734735277 å¹¶éç®åºåãæ¯å¦ä¿®æ£ç±ä¸å¡ç¡®è®¤ã ## åãæ¹å¨æ¸ å ### 4.1 å端ï¼yudao-module-mesï¼ | æä»¶ | æ¹å¨ | |------|------| | `dal/dataobject/wm/returnsales/MesWmReturnSalesDO` | å¢å `productSalesId` / `productSalesCode` | | `dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO` | å¢å `productSalesLineId` | | `dal/mysql/wm/returnsales/MesWmReturnSalesLineMapper` | å¢å æåºåºè¡ç»è®¡å·²éæ°éçæ¹æ³ãæåºåºè¡æ¥è¯¢éè´§è¡çæ¹æ³ | | `dal/mysql/wm/productsales/MesWmProductSalesLineMapper` | å¢å `selectListBySalesIds`ï¼æ¹éï¼ | | `controller/admin/wm/returnsales/vo/MesWmReturnSalesSaveReqVO` ç | å¢å åºåºå/åºåºè¡å段 | | `controller/admin/wm/returnsales/MesWmReturnSalesController` | æ°å¢å¯éåå页ãå¯éè¡å表两个æ¥å£ | | `controller/admin/wm/returnsales/vo/...`ï¼æ°å¢ï¼ | å¯éå RespVOãå¯éè¡ RespVO | | `service/wm/returnsales/MesWmReturnSalesService(Impl)` | åºåºåæ ¡éªãå¯éå页ãæäº¤æ¶æ°é夿 ¸ãå»æè´¨æ£åæ¯ | | `service/wm/returnsales/MesWmReturnSalesLineService(Impl)` | åºåºè¡ä¸è´æ§æ ¡éªãå¯éæ°éæ ¡éªãæ¹æ¬¡å·è¡¥å ¨ãå é¤ RQC ååæ¹æ³ | | `service/wm/returnsales/MesWmReturnSalesDetailService(Impl)` | æç»æ¹æ¬¡å¼ºå¶ç»§æ¿è¡ã䏿¶åæ¹æ¬¡æ ¡éª | | `service/wm/productsales/MesWmProductSalesService(Impl)` / `LineServiceImpl` | 廿 OQC å建ä¸ååï¼æäº¤ç´æ¥è¿å¾ æ£è´§ | | `service/qc/rqc/MesQcRqcServiceImpl` | ä¿çæ¥æºåæ®ç±»å忝ï¼ä¸å为éè´§åå建 RQC | | `enums/wm/MesWmReturnSalesStatusEnum` / `MesWmProductSalesStatusEnum` | ä¿ç 1ï¼å¾ æ£éª/å¾ æ£æµï¼ä» ä½åå²å ¼å®¹ï¼æ³¨éæ æ³¨åºå¼ | | `sql/mysql/20261028_return_sales_from_outbound.sql` | ä¸è¿° DDL | ### 4.2 å端ï¼mom-pro2-beforeï¼å¾ ææåä¿®æ¹ï¼ | æä»¶ | æ¹å¨ | |------|------| | `views/wls/returnsales/data.ts` | 表头å åºåºåéæ©ï¼è¡è¡¨åæ¹ä¸ºåºåºè¡éæ©ãæ¹æ¬¡è§£ç¦ï¼å»æè´¨æ£åä¸å¼å ³ï¼è¡¨æ ¼å å·²é/å¯éå | | `views/wls/returnsales/index.vue` | å»æãæ§è¡è´¨æ£ãæé®ä¸æç¤ºï¼åæ¶æé®ç¶æèå´è°æ´ | | `views/wls/returnsales/modules/line-list.vue` | æ·»å ç©ææ¹ä¸ºä»åºåºè¡éæ©ï¼æä¿çæå·¥ + åºåºè¡ä¸æï¼ | | `views/wls/returnsales/modules/detail-form.vue` | æ¹æ¬¡åªè¯»ç»§æ¿ | | `views/wls/productsales/data.ts`ã`views/wls/salesnotice/data.ts` å对åºåç»ä»¶ | å»æè´¨æ£å/å¼å ³ | | `api/mes/wm/returnsales/*` | å¢å å¯éå/å¯éè¡æ¥å£ï¼åæ®µåæ¥ | ## äºã宿½é¡ºåº 1. DDL + DO/VO åæ®µï¼å¯ä¸ç°æé»è¾å¹¶åï¼ä¸ç ´å线ä¸ï¼ã 2. å¯éåå页ãå¯éè¡å表æ¥å£ï¼åªè¯»ï¼å 让å端è½èè°ï¼ã 3. éè´§åä¿å/æäº¤æ ¡éªï¼åºåºåãè¡ãæ°éãæ¹æ¬¡ï¼ã 4. 䏿¶æç»æ¹æ¬¡ç»§æ¿ + å ¥åºåæ ¡éªï¼ä¿®å¤æ¹æ¬¡ä¸¢å¤±ï¼ã 5. å»è´¨æ£ï¼å å ³ææ°åæ®çè´¨æ£å ¥å£ä¸ç¶æåæ¯ï¼åæ¸ çåå²å¨éåæ®ã 6. å端æ¹é ä¸èè°ã ## å ãå¾ ç¡®è®¤ 1. **å»è´¨æ£èå´**ï¼æ¯å¦ç¡®è®¤åæ¶å»æãéå®åºåº OQCãåãåè´§éç¥æ¯å¦æ£éªãï¼è¿æ¯åªå»æéå®éè´§ RQCï¼ 2. **åºåºåç¶æèå´**ï¼æ¯å¦åªå 许对ã已宿(4)ãçéå®åºåºåéè´§ï¼æ¯å¦ä¹å 许ãå¾ æ§è¡åºåº(3)ãé¢ç»è®°ï¼ 3. **éè´§ç²åº¦**ï¼æåºåºè¡ï¼ç©æ+æ¹æ¬¡+æ°éï¼å³å¯ï¼è¿æ¯éè¦æåºåºæç»ï¼å«è¢ç ãåºåºåºä½ï¼éä»¶éåï¼ 4. **æ°æ®åºè´¨æ£å**ï¼ä¿çåºå¼ï¼å»ºè®®ï¼è¿æ¯å é¤ï¼ 5. **éè´§å 1 æ°æ®**ï¼åæ¶éåï¼è¿æ¯äººå·¥ä¿®æ£ç©æä¸æ¹æ¬¡ï¼ 6. å®å模åéè¿ RPC å建çéè´§åæ¯å¦å 许没æåºåºåå ³èï¼å»ºè®®å 许ï¼å¦åå®åæµç¨ä¼è¢«é»æï¼ï¼ docs/sale_return_from_outbound_frontend.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,240 @@ # éå®éè´§æåºåºåéè´§ + éå®ä»åºå»è´¨æ£ - å端èè°æ¹æ¡ ## æ¶åé¡µé¢ - éå®ä»åº / éå®éè´§ï¼åè¡¨ãæ°å¢/ç¼è¾ã详æ ã䏿¶æç»å¼¹çª - éå®ä»åº / éå®åºåºï¼åè¡¨ãæ°å¢/ç¼è¾ã详æ - éå®ä»åº / åè´§éç¥ï¼åè¡¨ãæ°å¢/ç¼è¾ã详æ ## ä¸å¡æµç¨ä¸æ°æ®å¸¦å ¥ 1. æ°å¢éè´§åï¼éæ©**éå®åºåºå**ï¼ä» å·²å®æç¶æãåå¨å¯éè¡ï¼â åºåºåå·ã客æ·ãå¯éè¡èªå¨å¸¦å ¥éè´§åã 2. åºåºå -> éè´§è¡ï¼ç©æãæ¹æ¬¡ãæ¹æ¬¡å·ãåºåºæ°éã已鿰éãå¯éæ°é忥èªåºåºè¡ï¼éè´§æ°éé»è®¤çäºå¯éæ°éãä¸é为å¯éæ°éã 3. éè´§è¡ -> 䏿¶æç»ï¼ç©æãæ¹æ¬¡ä¸å¯ç¼è¾ï¼å ¨é¨ç±éè´§è¡å¸¦å ¥ï¼åªéå¡«åä»åº/åºåº/åºä½/æ°éã 4. æäº¤éè´§åï¼ä¸åç»è¿è´¨æ£ï¼ç¶æç´æ¥ç±ãè稿ãå为ãå¾ æ§è¡ãã 5. æ§è¡éè´§ -> æ§è¡ä¸æ¶ï¼ä¸æ¶æç»çæ¹æ¬¡ä¸éè´§è¡æ¹æ¬¡ä¿æä¸è´ï¼å ¥åºæµæ°´æºå¸¦æ¹æ¬¡å·ã ## API ### 1. å¯ééå®åºåºååé¡µï¼æ°å¢ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/mes/wm/return-sales/returnable-product-sales-page` | ä» è¿å已宿ä¸åå¨å¯éè¡ï¼åºåºæ°é > 已鿰éï¼çéå®åºåºå | **请æ±åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | pageNo | Integer | æ¯ | 页ç | | pageSize | Integer | æ¯ | æ¯é¡µæ¡æ° | | code | String | å¦ | åºåºåå·ï¼æ¨¡ç³ï¼ | | name | String | å¦ | åºåºååç§°ï¼æ¨¡ç³ï¼ | | clientId | Long | å¦ | å®¢æ· ID | | shipmentDate | Date[] | å¦ | åºåºæ¥æèå´ | | outboundTime | DateTime[] | å¦ | å®é åºåºæ¶é´èå´ | **ååºå段ï¼** | åæ®µ | ç±»å | 说æ | |------|------|------| | id | Long | éå®åºåºå ID | | code | String | åºåºåå· | | name | String | åºåºååç§° | | clientId | Long | å®¢æ· ID | | clientName | String | 客æ·åç§° | | salesDate | DateTime | åºåºæ¥æ | | outboundTime | DateTime | å®é åºåºæ¶é´ | **ååºç¤ºä¾ï¼** ```json { "code": 0, "data": { "list": [ { "id": 1, "code": "PS2026030001", "name": "产ååºåºå", "clientId": 10, "clientName": "XX客æ·", "salesDate": "2026-03-01 00:00:00", "outboundTime": "2026-03-02 10:00:00" } ], "total": 1 } } ``` ### 2. éå®åºåºåå¯éè¡åè¡¨ï¼æ°å¢ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | `/mes/wm/return-sales/returnable-product-sales-line-list` | è¿åæå®åºåºåä¸å¯éæ°éå¤§äº 0 çè¡ | **请æ±åæ°ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | productSalesId | Long | æ¯ | éå®åºåºå ID | **ååºå段ï¼** | åæ®µ | ç±»å | 说æ | |------|------|------| | productSalesLineId | Long | éå®åºåºåè¡ IDï¼éè´§è¡å¿ é¡»æºå¸¦ï¼ | | salesId | Long | éå®åºåºå ID | | itemId | Long | ç©æ ID | | itemCode | String | ç©æç¼ç | | itemName | String | ç©æåç§° | | itemSpecification | String | è§æ ¼åå· | | itemUnit | String | 计éåä½ | | batchId | Long | æ¹æ¬¡ ID | | batchCode | String | æ¹æ¬¡å· | | outboundQuantity | BigDecimal | åºåºæ°é | | returnedQuantity | BigDecimal | 已鿰éï¼ä¸å«å·²åæ¶éè´§åï¼ | | returnableQuantity | BigDecimal | å¯éæ°é = åºåºæ°é - 已鿰é | **ååºç¤ºä¾ï¼** ```json { "code": 0, "data": [ { "productSalesLineId": 21, "salesId": 1, "itemId": 114, "itemCode": "M001", "itemName": "ç©æA", "itemSpecification": "100*200", "itemUnit": "个", "batchId": 4846066734735277, "batchCode": "4846066734735277", "outboundQuantity": 100.00, "returnedQuantity": 0.00, "returnableQuantity": 100.00 } ] } ``` ### 3. éè´§åä¿åï¼å段æ°å¢ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/mes/wm/return-sales/create` | å建éè´§å | | PUT | `/mes/wm/return-sales/update` | ä¿®æ¹éè´§å | **请æ±åæ°æ°å¢ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | productSalesId | Long | å¦ | éå®åºåºå IDï¼ä¼ äºåå¿ é¡»ä»è¯¥åºåºåçå¯éè¡ä¸éæ©éè´§è¡ | `productSalesCode` ç±åç«¯æ ¹æ®åºåºååå¡«ï¼å端æ éä¼ ã **ååºå段æ°å¢ï¼è¯¦æ /å表ï¼ï¼** | åæ®µ | ç±»å | 说æ | |------|------|------| | productSalesId | Long | éå®åºåºå ID | | productSalesCode | String | éå®åºåºåå· | **注æï¼** éè´§åå·²åå¨éè´§è¡æ¶ï¼ä¸å è®¸æ´æ¢ `productSalesId`ã ### 4. éè´§è¡ä¿åï¼å段æ°å¢/åæ´ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/mes/wm/return-sales-line/create` | å建éè´§è¡ | | PUT | `/mes/wm/return-sales-line/update` | ä¿®æ¹éè´§è¡ | **请æ±åæ°æ°å¢ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | productSalesLineId | Long | æ¡ä»¶å¿ å¡« | éè´§åå ³èäºåºåºåæ¶å¿ å¡« | **请æ±åæ°ç§»é¤ï¼** | åæ° | 说æ | |------|------| | rqcCheckFlag | éå®ä»åºä¸åè´¨æ£ï¼éè´§è¡ä¸åéè¦è¯¥å段 | **åæ®µå¸¦å ¥è§åï¼** | åæ®µ | è§å | |------|------| | itemId | å端以åºåºè¡çç©æä¸ºåï¼åç«¯ä¼ å¼ä¼è¢«è¦ç | | batchId / batchCode | å端以åºåºè¡çæ¹æ¬¡ä¸ºåï¼åç«¯ä¼ å¼ä¼è¢«è¦ç | | quantity | å¿ é¡»å¤§äº 0 ä¸ä¸è¶ è¿å¯éæ°é | ### 5. éè´§åæäº¤ï¼è¡ä¸ºåæ´ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | PUT | `/mes/wm/return-sales/submit` | æäº¤åç¶æç´æ¥å为ãå¾ æ§è¡ãï¼ä¸åç»è¿ãå¾ æ£éªã | **æ ¡éªï¼** æäº¤æ¶ä¼éæ°æ ¡éªéè´§è¡ä¸åºåºåçå½å±å ³ç³»ï¼ä»¥ååè¡æ°éä¹åä¸è¶ è¿å¯éæ°éï¼è稿æé´è¢«å ¶å®éè´§åå ç¨æ¶ä¼æç¤ºãéè´§æ°éä¸è½è¶ è¿å¯éæ°éãã ### 6. 䏿¶æç»ä¿åï¼è¡ä¸ºåæ´ï¼ | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | POST | `/mes/wm/return-sales-detail/create` | 䏿¶æç» | | PUT | `/mes/wm/return-sales-detail/update` | 䏿¶æç» | **è§ååæ´ï¼** | åæ®µ | è§å | |------|------| | itemId | 以éè´§è¡ä¸ºåï¼åç«¯ä¼ å¼ä¼è¢«è¦ç | | batchId / batchCode | 以éè´§è¡ä¸ºåï¼ä¼ å ¥ä¸è¡ä¸ä¸è´çæ¹æ¬¡ä¼æ¥éã䏿¶æç»çæ¹æ¬¡å¿ é¡»ä¸éè´§è¡æ¹æ¬¡ä¸è´ã | | quantity | ä¸è¶ è¿éè´§è¡æ°é | 䏿¶æç»è¡¨åä¸çæ¹æ¬¡åºæ¹ä¸ºåªè¯»å±ç¤ºï¼ä¸åæä¾æ¹æ¬¡éæ©/æå·¥è¾å ¥ã ### 7. éå®åºåº / åè´§éç¥ï¼è´¨æ£ç¸å ³æ¥å£ä¿çä½ä¸å使ç¨ï¼ | åºæ¯ | åæ´ | |------|------| | éå®åºåºæäº¤ | ç´æ¥ç±ãè稿ãå为ãå¾ æ£è´§ãï¼ä¸åçæ OQC æ£éªå | | éå®åºåºè¡ç¼è¾ | ä¸åèªå¨å建 OQC æ£éªå | | åè´§éç¥çæéå®åºåº | ä¸åå¤å¶è´¨æ£æ è¯å°åºåºè¡ | | éè´§åæäº¤ | ä¸åè¿å ¥ãå¾ æ£éªãï¼ä¸åçæ RQC æ£éªå | ## åæ®µå±ç¤ºè§å | åæ®µ | å±ç¤ºä½ç½® | 说æ | |------|----------|------| | éå®åºåºåå· | éè´§åå表ã详æ | æ°å¢åï¼å±ç¤º `productSalesCode` | | åºåºåéæ© | æ°å¢/ç¼è¾éè´§å | å¿ å¡«ï¼æ°æµç¨ï¼ï¼åªè¯»å±ç¤ºéä¸åºåºå | | å¯éè¡éæ© | æ°å¢/ç¼è¾éè´§å | ç¹å»ãéæ©åºåºè¡ãæå¼å¯éè¡å¼¹çª | | åºåºæ°é | å¯éè¡å¼¹çª | æ¥èª `outboundQuantity` | | 已鿰é | å¯éè¡å¼¹çª | æ¥èª `returnedQuantity` | | å¯éæ°é | å¯éè¡å¼¹çªãéè´§è¡ | æ¥èª `returnableQuantity`ï¼éè´§æ°éä¸è½è¶ è¿è¯¥å¼ | | æ¹æ¬¡å· | éè´§è¡ã䏿¶æç» | åªè¯»ï¼æ¥èªåºåºè¡ | | è´¨æ£ç¶æ | éè´§åãéå®åºåºå表 | ä¸åå±ç¤ºè´¨æ£ç¶æå | ## ä¸å¡è§å说æ | åºæ¯ | è§å | |------|------| | å¯éåºåºåèå´ | ä» ã已宿ãç¶æï¼ä¸è³å°æä¸è¡å¯éæ°éå¤§äº 0 | | å¯éæ°é | åºåºè¡æ°é - è¯¥è¡æææªåæ¶éè´§åçéè´§æ°éä¹å | | éè´§è¡æ¥æº | å ³èäºåºåºåçéè´§åï¼ææè¡å¿ é¡»æ¥èªè¯¥åºåºå | | éå¤éè´§ | 夿¬¡é货累计ä¸è¶ è¿åºåºæ°é | | æ¹æ¬¡æµè½¬ | åºåºè¡æ¹æ¬¡ â éè´§è¡æ¹æ¬¡ â 䏿¶æç»æ¹æ¬¡ â å ¥åºæµæ°´æ¹æ¬¡ï¼å ¨ç¨ä¸è´ | | ç¶ææµè½¬ | è稿(0) â å¾ æ§è¡(2) â å¾ ä¸æ¶(3) â 已宿(4)ï¼åæ¶(5) | | å®åæ¥æºéè´§å | å®å模åå建çéè´§åæ²¡æåºåºåä¸ä¸æï¼`productSalesId` 为空ï¼ä»èµ°åæµç¨ | ## 注æäºé¡¹ - æ°å¢éè´§åæ¶è¥æªéæ©éå®åºåºåï¼å端ä¸ä¼å¼ºå¶è¦æ± `productSalesLineId`ï¼ä½åç«¯æ°æµç¨åºå¼å¯¼ç¨æ·å éåºåºåã - å¯éè¡å¼¹çªæ°æ®é卿¯æ¬¡æå¼æ¶éæ°æåï¼é¿å ç¨æ·åçæé´è¢«å ¶å®éè´§åå ç¨å¯¼è´æäº¤å¤±è´¥ã - éè´§æ°éé»è®¤å¸¦å ¥å¯éæ°éï¼ç¨æ·å¯å°äºè¯¥å¼ï¼è¶ è¿ä¼å¨ä¿ååæäº¤æ¶åæ ¡éªä¸æ¬¡ã - 䏿¶æç»çæ¹æ¬¡åæ®µå¿ é¡»æ¹ä¸ºåªè¯»ï¼é¿å ç¨æ·æå·¥å¡«åå¯¼è´æ¹æ¬¡æ ¡éªå¤±è´¥ã - éå®åºåºãåè´§éç¥é¡µé¢çè´¨æ£å¼å ³ãè´¨æ£ç¶æåãè´¨æ£åå ¥å£éè¦ä¸å¹¶ç§»é¤ï¼å¦åä¼äº§çæ°¸è¿æ æ³æ¨è¿çãå¾ æ£æµãç¶æå ¥å£ã sql/mysql/20261028_return_sales_from_outbound.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ -- éå®éè´§æ¹é ï¼éè´§åå ³èéå®åºåºåï¼æåºåºè¡éè´§ï¼ -- 说æï¼product_sales_id å 许为空ï¼å ¼å®¹å®å模åéè¿ RPC å建çéè´§å ALTER TABLE mes_wm_return_sales ADD COLUMN product_sales_id BIGINT NULL COMMENT 'éå®åºåºåç¼å·' AFTER sale_order_id, ADD COLUMN product_sales_code VARCHAR(100) NULL COMMENT 'éå®åºåºåå·ï¼åä½ï¼' AFTER product_sales_id; ALTER TABLE mes_wm_return_sales_line ADD COLUMN product_sales_line_id BIGINT NULL COMMENT 'éå®åºåºåè¡ç¼å·' AFTER return_id; CREATE INDEX idx_return_sales_product_sales ON mes_wm_return_sales (product_sales_id); CREATE INDEX idx_return_sales_line_product_sales_line ON mes_wm_return_sales_line (product_sales_line_id); yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesController.java
@@ -10,9 +10,13 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnableProductSalesLineRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnableProductSalesRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; import io.swagger.v3.oas.annotations.Operation; @@ -138,6 +142,25 @@ return success(true); } @GetMapping("/returnable-product-sales-page") @Operation(summary = "è·å¾å¯ééå®åºåºåå页", description = "ä» å·²å®æç¶æï¼ä¸åå¨å¯éæ°éå¤§äº 0 çè¡") @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") public CommonResult<PageResult<MesWmReturnableProductSalesRespVO>> getReturnableProductSalesPage( @Valid MesWmProductSalesPageReqVO pageReqVO) { PageResult<MesWmProductSalesDO> pageResult = returnSalesService.getReturnableProductSalesPage(pageReqVO); List<MesWmReturnableProductSalesRespVO> list = buildReturnableProductSalesRespVOList(pageResult.getList()); return success(new PageResult<>(list, pageResult.getTotal())); } @GetMapping("/returnable-product-sales-line-list") @Operation(summary = "è·å¾éå®åºåºåå¯éè¡å表") @Parameter(name = "productSalesId", description = "éå®åºåºåç¼å·", required = true) @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") public CommonResult<List<MesWmReturnableProductSalesLineRespVO>> getReturnableProductSalesLineList( @RequestParam("productSalesId") Long productSalesId) { return success(returnSalesService.getReturnableProductSalesLineList(productSalesId)); } @GetMapping("/check-quantity") @Operation(summary = "æ ¡éªéå®éè´§åæ°é", description = "æ ¡éªæ¯è¡æç»æ°éä¹åæ¯å¦çäºè¡éè´§æ°é") @Parameter(name = "id", description = "ç¼å·", required = true) @@ -161,4 +184,16 @@ vo.setClientName(customer.getName()))); } private List<MesWmReturnableProductSalesRespVO> buildReturnableProductSalesRespVOList( List<MesWmProductSalesDO> list) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } Map<Long, CrmCustomerRespDTO> customerMap = crmCustomerApi.getCustomerMap( convertSet(list, MesWmProductSalesDO::getClientId)); return BeanUtils.toBean(list, MesWmReturnableProductSalesRespVO.class, vo -> MapUtils.findAndThen(customerMap, vo.getClientId(), customer -> vo.setClientName(customer.getName()))); } } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java
@@ -30,6 +30,12 @@ @Schema(description = "客æ·åç§°", example = "XX客æ·") private String clientName; @Schema(description = "éå®åºåºå ID", example = "1") private Long productSalesId; @Schema(description = "éå®åºåºåå·", example = "PS2026030001") private String productSalesCode; @Schema(description = "éè´§æ¥æ") private LocalDate returnDate; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesSaveReqVO.java
@@ -31,6 +31,12 @@ @NotNull(message = "å®¢æ· ID ä¸è½ä¸ºç©º") private Long clientId; @Schema(description = "éå®åºåºå ID", example = "1") private Long productSalesId; @Schema(description = "éå®åºåºåå·ï¼åç«¯æ ¹æ®åºåºååå¡«ï¼å端æ éä¼ ï¼", example = "PS2026030001") private String productSalesCode; @Schema(description = "éè´§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "éè´§æ¥æä¸è½ä¸ºç©º") private LocalDate returnDate; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnableProductSalesLineRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,53 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; /** * 管çåå° - å¯ééå®åºåºåè¡ Response VO * * @author è¶ çº§ç®¡çå */ @Schema(description = "管çåå° - å¯ééå®åºåºåè¡ Response VO") @Data public class MesWmReturnableProductSalesLineRespVO { @Schema(description = "éå®åºåºåè¡ ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long productSalesLineId; @Schema(description = "éå®åºåºå ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long salesId; @Schema(description = "ç©æ ID", example = "1") private Long itemId; @Schema(description = "ç©æç¼ç ", example = "M001") private String itemCode; @Schema(description = "ç©æåç§°", example = "ç©æA") private String itemName; @Schema(description = "è§æ ¼åå·", example = "100*200") private String itemSpecification; @Schema(description = "计éåä½", example = "个") private String itemUnit; @Schema(description = "æ¹æ¬¡ ID", example = "1") private Long batchId; @Schema(description = "æ¹æ¬¡å·", example = "B20250101") private String batchCode; @Schema(description = "åºåºæ°é", example = "100.00") private BigDecimal outboundQuantity; @Schema(description = "已鿰é", example = "10.00") private BigDecimal returnedQuantity; @Schema(description = "å¯éæ°é", example = "90.00") private BigDecimal returnableQuantity; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnableProductSalesRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,38 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; /** * 管çåå° - å¯ééå®åºåºå Response VO * * @author è¶ çº§ç®¡çå */ @Schema(description = "管çåå° - å¯ééå®åºåºå Response VO") @Data public class MesWmReturnableProductSalesRespVO { @Schema(description = "ç¼å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; @Schema(description = "åºåºåå·", example = "PS2026030001") private String code; @Schema(description = "åºåºååç§°", example = "产ååºåºå") private String name; @Schema(description = "å®¢æ· ID", example = "1") private Long clientId; @Schema(description = "客æ·åç§°", example = "XX客æ·") private String clientName; @Schema(description = "åºåºæ¥æ") private LocalDateTime salesDate; @Schema(description = "å®é åºåºæ¶é´") private LocalDateTime outboundTime; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineRespVO.java
@@ -21,6 +21,9 @@ @Schema(description = "éè´§åID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long returnId; @Schema(description = "éå®åºåºåè¡ ID", example = "1") private Long productSalesLineId; @Schema(description = "ç©æID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long itemId; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java
@@ -23,6 +23,9 @@ @NotNull(message = "éè´§åIDä¸è½ä¸ºç©º") private Long returnId; @Schema(description = "éå®åºåºåè¡ ID", example = "1") private Long productSalesLineId; @Schema(description = "ç©æID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "ç©æIDä¸è½ä¸ºç©º") private Long itemId; @@ -37,9 +40,6 @@ @Schema(description = "æ¹æ¬¡å·", example = "B20250101") private String batchCode; @Schema(description = "æ¯å¦éè¦è´¨æ£", example = "true") private Boolean rqcCheckFlag; @Schema(description = "夿³¨", example = "夿³¨") private String remark; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java
@@ -45,6 +45,17 @@ */ private Long clientId; /** * éå®åºåºå ID * * å ³è {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO#getId()} * å 许为空ï¼å®å模åå建çéè´§åæ²¡æåºåºåä¸ä¸æ */ private Long productSalesId; /** * éå®åºåºåå·ï¼åä½ï¼ */ private String productSalesCode; /** * éè´§æ¥æ */ private LocalDate returnDate; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java
@@ -37,6 +37,13 @@ */ private Long returnId; /** * éå®åºåºåè¡ ID * * å ³è {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO#getId()} * å 许为空ï¼å®å模åå建çéè´§åæ²¡æåºåºåä¸ä¸æ */ private Long productSalesLineId; /** * ç©æ ID * * å ³è {@link MesMdItemDO#getId()} yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java
@@ -54,6 +54,35 @@ return selectPage(reqVO, wrapper); } /** * å页æ¥è¯¢å¯ééå®åºåºåï¼ä» å·²å®æç¶æï¼ä¸åå¨ãåºåºæ°é > 已鿰éãçè¡ */ default PageResult<MesWmProductSalesDO> selectReturnablePage(MesWmProductSalesPageReqVO reqVO, Integer finishedStatus, Integer canceledStatus, List<Long> permittedClientIds) { LambdaQueryWrapperX<MesWmProductSalesDO> wrapper = new LambdaQueryWrapperX<MesWmProductSalesDO>() .likeIfPresent(MesWmProductSalesDO::getCode, reqVO.getCode()) .likeIfPresent(MesWmProductSalesDO::getName, reqVO.getName()) .eqIfPresent(MesWmProductSalesDO::getClientId, reqVO.getClientId()) .eq(MesWmProductSalesDO::getStatus, finishedStatus) .betweenIfPresent(MesWmProductSalesDO::getSalesDate, reqVO.getShipmentDate()) .betweenIfPresent(MesWmProductSalesDO::getOutboundTime, reqVO.getOutboundTime()); if (permittedClientIds != null) { if (CollUtil.isEmpty(permittedClientIds)) { return PageResult.empty(); } wrapper.in(MesWmProductSalesDO::getClientId, permittedClientIds); } wrapper.apply("EXISTS (SELECT 1 FROM mes_wm_product_sales_line psl " + "WHERE psl.deleted = 0 AND psl.sales_id = mes_wm_product_sales.id AND psl.quantity > " + "(SELECT IFNULL(SUM(rl.quantity), 0) FROM mes_wm_return_sales_line rl " + "INNER JOIN mes_wm_return_sales rs ON rs.id = rl.return_id AND rs.deleted = 0 " + "WHERE rl.deleted = 0 AND rl.product_sales_line_id = psl.id AND rs.status != {0}))", canceledStatus); wrapper.orderByDesc(MesWmProductSalesDO::getId); return selectPage(reqVO, wrapper); } default MesWmProductSalesDO selectByCode(String code) { return selectOne(MesWmProductSalesDO::getCode, code); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesLineMapper.java
@@ -1,12 +1,17 @@ package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.math.BigDecimal; import java.util.Collection; import java.util.List; /** @@ -34,4 +39,31 @@ .eq(MesWmReturnSalesLineDO::getReturnId, returnId)); } default List<MesWmReturnSalesLineDO> selectListByProductSalesLineIds(Collection<Long> productSalesLineIds) { return selectList(new LambdaQueryWrapperX<MesWmReturnSalesLineDO>() .in(MesWmReturnSalesLineDO::getProductSalesLineId, productSalesLineIds)); } /** * ç»è®¡æ¯ä¸ªéå®åºåºè¡å·²è¢«éè´§çæ°éï¼æé¤å·²åæ¶çéè´§ååå·²å é¤çè¡ * * @param productSalesLineIds éå®åºåºè¡ ID éå * @param canceledStatus éè´§åå·²åæ¶ç¶æ * @param excludeReturnId éè¦æé¤çéè´§å IDï¼æ ¡éªå½åéè´§åèªèº«çå¯éæ°éæ¶ä½¿ç¨ï¼ï¼å¯ä¸ºç©º * @return key=éå®åºåºè¡ IDï¼value=已鿰é */ @Select("<script>" + "SELECT rl.product_sales_line_id AS `key`, IFNULL(SUM(rl.quantity), 0) AS `value` " + "FROM mes_wm_return_sales_line rl " + "INNER JOIN mes_wm_return_sales rs ON rs.id = rl.return_id AND rs.deleted = 0 AND rs.status != #{canceledStatus} " + "<if test='excludeReturnId != null'>AND rs.id != #{excludeReturnId} </if>" + "WHERE rl.deleted = 0 AND rl.product_sales_line_id IN " + "<foreach collection='productSalesLineIds' item='id' open='(' separator=',' close=')'>#{id}</foreach> " + "GROUP BY rl.product_sales_line_id" + "</script>") List<KeyValue<Long, BigDecimal>> selectReturnedQuantityList( @Param("productSalesLineIds") Collection<Long> productSalesLineIds, @Param("canceledStatus") Integer canceledStatus, @Param("excludeReturnId") Long excludeReturnId); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -672,8 +672,16 @@ ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_713_006, "éå®éè´§åè¡æ°éä¸æç»æ°éä¸ä¸è´"); ErrorCode WM_RETURN_SALES_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_007, "éå®éè´§å已宿æå·²åæ¶ï¼æ æ³åæ¶"); ErrorCode WM_RETURN_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "éå®éè´§åè¡ä¸åå¨"); ErrorCode WM_RETURN_SALES_PRODUCT_SALES_NOT_EXISTS = new ErrorCode(1_040_713_008, "éå®åºåºåä¸åå¨"); ErrorCode WM_RETURN_SALES_PRODUCT_SALES_NOT_FINISHED = new ErrorCode(1_040_713_009, "åªæå·²å®æç¶æçéå®åºåºåæå 许éè´§"); ErrorCode WM_RETURN_SALES_CLIENT_MISMATCH = new ErrorCode(1_040_713_010, "éè´§å客æ·ä¸éå®åºåºå客æ·ä¸ä¸è´"); ErrorCode WM_RETURN_SALES_PRODUCT_SALES_IMMUTABLE = new ErrorCode(1_040_713_011, "å·²åå¨éè´§è¡ï¼ä¸è½æ´æ¢éå®åºåºå"); ErrorCode WM_RETURN_SALES_LINE_PRODUCT_SALES_REQUIRED = new ErrorCode(1_040_713_101, "已鿩éå®åºåºåï¼éè´§è¡å¿ é¡»ä»åºåºåè¡ä¸éæ©"); ErrorCode WM_RETURN_SALES_LINE_PRODUCT_SALES_NOT_MATCH = new ErrorCode(1_040_713_102, "éå®åºåºåè¡ä¸å±äºæéçéå®åºåºå"); ErrorCode WM_RETURN_SALES_LINE_QUANTITY_EXCEED = new ErrorCode(1_040_713_103, "éè´§æ°éä¸è½è¶ è¿å¯éæ°é"); ErrorCode WM_RETURN_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "éå®éè´§åæç»ä¸åå¨"); ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_713_201, "䏿¶æç»æ»æ°éä¸è½è¶ è¿éè´§è¡æ°é"); ErrorCode WM_RETURN_SALES_DETAIL_BATCH_MISMATCH = new ErrorCode(1_040_713_202, "䏿¶æç»çæ¹æ¬¡å¿ é¡»ä¸éè´§è¡æ¹æ¬¡ä¸è´"); // ========== MES ä»åºç®¡ç-çç¹æ¹æ¡/ä»»å¡/ç»æï¼1-040-714-100ï¼ ========== ErrorCode WM_STOCK_TAKING_PLAN_NOT_EXISTS = new ErrorCode(1_040_714_100, "çç¹æ¹æ¡ä¸åå¨"); yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/seedquality/MesQcSeedQualityServiceImpl.java
@@ -193,6 +193,8 @@ if (qualifiedWarehouse == null) throw exception(WM_WAREHOUSE_NOT_EXISTS); if (!MesWmWarehouseTypeEnum.QUALIFIED.getType().equals(qualifiedWarehouse.getType())) throw exception(WM_WAREHOUSE_TYPE_NOT_QUALIFIED); // æåæ ¡éªåæ ¼åºå·²é ç½®åºåº/åºä½ï¼é¿å 夿£å®¡æ ¸æ¾è¡æ¶æå¤±è´¥ resolveQualifiedLocation(qualifiedWarehouse); LocalDateTime now = LocalDateTime.now(); Long operatorId = getLoginUserId(); @@ -252,6 +254,8 @@ if (!MesWmWarehouseTypeEnum.QUALIFIED.getType().equals(qualifiedWarehouse.getType())) { throw exception(WM_WAREHOUSE_TYPE_NOT_QUALIFIED); } // æåæ ¡éªåæ ¼åºå·²é ç½®åºåº/åºä½ï¼é¿å 夿£å®¡æ ¸æ¾è¡æ¶æå¤±è´¥ resolveQualifiedLocation(qualifiedWarehouse); Set<String> codes = new HashSet<>(); boolean passed = true; MesQcSeedQualityDO quality = MesQcSeedQualityDO.builder().code(bag.getCode()).itemId(batch.getItemId()) @@ -296,12 +300,10 @@ Long qualifiedLocationId = null; Long qualifiedAreaId = null; if (passed) { List<MesWmWarehouseLocationDO> locations = warehouseLocationService.getWarehouseLocationList(qualifiedWarehouse.getId()); if (CollUtil.isNotEmpty(locations)) { qualifiedLocationId = locations.get(0).getId(); List<MesWmWarehouseAreaDO> areas = warehouseAreaService.getWarehouseAreaList(qualifiedLocationId); if (CollUtil.isNotEmpty(areas)) qualifiedAreaId = areas.get(0).getId(); } // åºåäºå¡å¿ é¡»è½å°åºåºãåºä½ï¼åæ ¼åºç¼ºå°é ç½®æ¶æåç»åºå¯æä½çæç¤º Long[] target = resolveQualifiedLocation(qualifiedWarehouse); qualifiedLocationId = target[0]; qualifiedAreaId = target[1]; } // æè¢ç ç²åº¦æµè½¬åºåï¼éå®è¯¥è¢å¨æååºä¸çæ´»å¨æç»ï¼ç¦æ¢ææ¹æ¬¡ä»»ææ£å MesWmMaterialStockBagDO stockBag = materialStockBagMapper.selectActiveByBagCode(bag.getCode()); @@ -688,8 +690,8 @@ * * @param tempStock 仿ååºæ£ååè¿åçæåè®°å½ï¼æºå¸¦ item/batch/vendor ç»´åº¦ï¼ * @param qualifiedWarehouseId ç®æ åæ ¼åºä»åºç¼å· * @param qualifiedLocationId ç®æ åæ ¼åºåºåºç¼å·ï¼æªé ç½®å为 nullï¼ * @param qualifiedAreaId ç®æ åæ ¼åºåºä½ç¼å·ï¼æªé ç½®å为 nullï¼ * @param qualifiedLocationId ç®æ åæ ¼åºåºåºç¼å· * @param qualifiedAreaId ç®æ åæ ¼åºåºä½ç¼å· */ private MesWmMaterialStockBagDO getOrCreateStockBag(MesProBagCodeDO bag, MesWmMaterialStockDO tempStock) { MesWmMaterialStockBagDO stockBag = materialStockBagMapper.selectByBagCode(bag.getCode()); @@ -706,6 +708,25 @@ return stockBag; } /** * è§£æåæ ¼åºçé»è®¤å ¥åºåºåºä¸åºä½ï¼å第ä¸ä¸ªåæ¶é ç½®äºåºä½çéå»ç»åºåºã * * è´¨æ£æä»åºç»´åº¦éæ©å ¥åºç®æ ï¼åºåº/åºä½ç±ç³»ç»èªå¨è½ç¹ï¼åæ ¼åºç¼ºå°å¯ç¨åºåºæåºä½æ¶ï¼ * åºåäºå¡æ æ³åå ¥ï¼ç´æ¥æç¤ºç®¡çåå®åä»åºé ç½®ã */ private Long[] resolveQualifiedLocation(MesWmWarehouseDO qualifiedWarehouse) { List<MesWmWarehouseLocationDO> locations = warehouseLocationService.getWarehouseLocationList(qualifiedWarehouse.getId()) .stream().filter(location -> !Boolean.TRUE.equals(location.getFrozen())).toList(); if (CollUtil.isEmpty(locations)) throw new IllegalArgumentException("åæ ¼åºã" + qualifiedWarehouse.getName() + "ãæªé ç½®å¯ç¨åºåºï¼è¯·å å¨ä»åºç®¡çä¸å®ååºåºä¸åºä½"); for (MesWmWarehouseLocationDO location : locations) { List<MesWmWarehouseAreaDO> areas = warehouseAreaService.getWarehouseAreaList(location.getId()) .stream().filter(area -> !Boolean.TRUE.equals(area.getFrozen())).toList(); if (CollUtil.isNotEmpty(areas)) return new Long[]{location.getId(), areas.get(0).getId()}; } throw new IllegalArgumentException("åæ ¼åºã" + qualifiedWarehouse.getName() + "ãæªé ç½®å¯ç¨åºä½ï¼è¯·å å¨ä»åºç®¡çä¸å®ååºåºä¸åºä½"); } private MesWmMaterialStockDO getOrCreateQualifiedStock(MesWmMaterialStockDO tempStock, Long qualifiedWarehouseId, Long qualifiedLocationId, Long qualifiedAreaId) { MesWmMaterialStockDO qualified = materialStockMapper.selectQualifiedByCompositeKey( yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
@@ -17,7 +17,6 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeLineService; import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; @@ -57,9 +56,6 @@ @Resource @Lazy private MesWmSalesNoticeLineService salesNoticeLineService; @Resource @Lazy private MesQcOqcService oqcService; @Override public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) { @@ -83,34 +79,6 @@ // æ´æ° MesWmProductSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesLineDO.class); productSalesLineMapper.updateById(updateObj); // æ£æ¥æ¯å¦éè¦å建 OQC æ£éªåï¼ä»ä¸éè¦æ£éªå为éè¦æ£éª if (Boolean.TRUE.equals(updateReqVO.getOqcCheckFlag()) && !Boolean.TRUE.equals(oldLine.getOqcCheckFlag())) { // è·ååºåºåä¿¡æ¯ MesWmProductSalesDO sales = productSalesService.getProductSales(updateReqVO.getSalesId()); if (sales == null) { log.warn("[updateProductSalesLine] åºåºåä¸åå¨ï¼salesId={}", updateReqVO.getSalesId()); return; } // æå»ºåºåºæç» DO MesWmProductSalesLineDO line = new MesWmProductSalesLineDO(); line.setId(updateReqVO.getId()); line.setItemId(updateReqVO.getItemId()); line.setBatchCode(updateReqVO.getBatchCode()); line.setQuantity(updateReqVO.getQuantity()); // å建 OQC æ£éªåï¼è®©å¼å¸¸æåº Long oqcId = oqcService.createOqcFromProductSales( sales.getId(), line, sales.getCode(), sales.getClientId()); // æ´æ°åºåºæç»ç oqcId åè´¨éç¶æ productSalesLineMapper.updateById(new MesWmProductSalesLineDO() .setId(updateReqVO.getId()) .setOqcId(oqcId) .setQualityStatus(MesWmQualityStatusEnum.PENDING.getStatus())); } } @Override yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
@@ -29,7 +29,6 @@ import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeQcStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockReserveBizTypeEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; @@ -43,10 +42,8 @@ import cn.iocoder.yudao.module.mes.service.wm.stockreserve.MesWmStockReserveService; import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -103,9 +100,6 @@ private MesWmMaterialStockService materialStockService; @Resource private MesWmStockReserveService stockReserveService; @Resource @Lazy private MesQcOqcService oqcService; @Resource private MesTraceIntegrityService integrityService; @@ -179,37 +173,7 @@ } } // è·ååºåºåä¿¡æ¯ MesWmProductSalesDO sales = productSalesMapper.selectById(id); // æ£æ¥ææè¡ç oqcCheckFlagï¼å¦ææéè¦ OQC æ£éªçè¡ï¼è¿å ¥å¾ æ£æµç¶æ boolean needOqc = CollectionUtils.anyMatch(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag())); if (needOqc) { // 为éè¦ OQC æ£éªä¸å°æªå建æ£éªåçæç»å建 OQC æ£éªå List<MesWmProductSalesLineDO> oqcLines = CollectionUtils.filterList(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) && line.getOqcId() == null); for (MesWmProductSalesLineDO line : oqcLines) { // ç´æ¥è°ç¨ï¼è®©å¼å¸¸æåºï¼ä¿è¯æ°æ®ä¸è´æ§ Long oqcId = oqcService.createOqcFromProductSales( sales.getId(), line, sales.getCode(), sales.getClientId()); // æ´æ°åºåºæç»ç oqcId productSalesLineMapper.updateById(new MesWmProductSalesLineDO() .setId(line.getId()) .setOqcId(oqcId)); } // æ¹éåå§å OQC è¡çè´¨éç¶æä¸º"å¾ æ£éª" List<Long> oqcLineIds = convertList( CollectionUtils.filterList(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag())), MesWmProductSalesLineDO::getId); productSalesLineService.updateProductSalesLineQualityStatus(oqcLineIds, MesWmQualityStatusEnum.PENDING.getStatus()); // éè¦æ£éªï¼è¿å ¥å¾ æ£æµ productSalesMapper.updateById(new MesWmProductSalesDO() .setId(id).setStatus(MesWmProductSalesStatusEnum.CONFIRMED.getStatus())); return; } // ä¸éè¦æ£éªï¼ç´æ¥è¿å ¥å¾ æ£è´§ // éå®ä»åºæµè½¬ä¸ç»è¿è´¨æ£ï¼æäº¤åç´æ¥è¿å ¥å¾ æ£è´§ productSalesMapper.updateById(new MesWmProductSalesDO() .setId(id).setStatus(MesWmProductSalesStatusEnum.APPROVING.getStatus())); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java
@@ -139,12 +139,27 @@ // æ ¡éªä»åºãåºåºãåºä½çå ³èå ³ç³» warehouseAreaService.validateWarehouseAreaExists( reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); // ç©æãæ¹æ¬¡ä»¥éè´§è¡ä¸ºåï¼éè´§æ¹æ¬¡æ¥èªéå®åºåºåï¼ä¸æ¶æ¶ä¸å è®¸åæ´ï¼ reqVO.setItemId(line.getItemId()); resolveBatch(reqVO, line); // æ ¡éªåºä½ç©æ/æ¹æ¬¡æ··æ¾è§å materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); // æ ¡éªæç»æ»æ°éä¸è¶ è¿è¡æ°éï¼æé¤èªèº«ï¼ validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); } // æ ¹æ® batchCode è§£æ batchIdï¼å¿ 须卿··æ¾è§åæ ¡éªä¹åï¼å 为å®ä¾èµ batchIdï¼ /** * è§£æä¸æ¶æç»æ¹æ¬¡ï¼è¡å·²æå®æ¹æ¬¡æ¶å¼ºå¶æ²¿ç¨ï¼å¦åææ¹æ¬¡å·è§£æ */ private void resolveBatch(MesWmReturnSalesDetailSaveReqVO reqVO, MesWmReturnSalesLineDO line) { if (line.getBatchId() != null) { if (reqVO.getBatchId() != null && ObjUtil.notEqual(reqVO.getBatchId(), line.getBatchId())) { throw exception(WM_RETURN_SALES_DETAIL_BATCH_MISMATCH); } reqVO.setBatchId(line.getBatchId()); reqVO.setBatchCode(line.getBatchCode()); return; } fillBatchId(reqVO); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineService.java
@@ -7,7 +7,9 @@ import jakarta.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; import java.util.Map; /** * MES éå®éè´§åè¡ Service æ¥å£ @@ -86,6 +88,15 @@ void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus); /** * ç»è®¡éå®åºåºè¡å·²éæ°éï¼æé¤å·²åæ¶çéè´§åï¼ * * @param productSalesLineIds éå®åºåºè¡ ID éå * @param excludeReturnId éè¦æé¤çéè´§å IDï¼æ ¡éªå½åéè´§åèªèº«æ¶ä½¿ç¨ï¼ï¼å¯ä¸ºç©º * @return key=éå®åºåºè¡ IDï¼value=已鿰é */ Map<Long, BigDecimal> getReturnedQuantityMap(Collection<Long> productSalesLineIds, Long excludeReturnId); /** * RQC æ£éªå®æåï¼æ ¹æ®åæ ¼å/ä¸åæ ¼åæ°éæ´æ°éå®éè´§åè¡ * * <p>æåé»è¾ï¼ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java
@@ -2,30 +2,36 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_REQUIRED; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_LINE_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES éå®éè´§åè¡ Service å®ç°ç±» @@ -43,12 +49,15 @@ @Lazy private MesWmReturnSalesService returnSalesService; @Resource private MesMdmItemService mdmItemService; private MdmItemApi mdmItemApi; @Resource private MesWmBatchService batchService; @Resource @Lazy private MesWmReturnSalesDetailService returnSalesDetailService; @Resource @Lazy private MesWmProductSalesLineService productSalesLineService; @Override public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) { @@ -79,12 +88,46 @@ /** * æ ¡éªä¿åæ¶çå ³èæ°æ® * * <p>éè´§åå ³èäºéå®åºåºåæ¶ï¼ç©æãæ¹æ¬¡ä¸å¾åèªåºåºè¡ï¼å¹¶æ ¡éªå¯éæ°éï¼ * æªå ³èåºåºåï¼å¦å®å模ååå»ºï¼æ¶ï¼ä¿æåæç©æ/æ¹æ¬¡æ ¡éªé»è¾ã */ private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) { // æ ¡éªéè´§ååå¨ + èç¨¿ç¶æ returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); if (returnSales.getProductSalesId() != null) { validateOutboundLine(reqVO, returnSales); return; } // æ ¡éªç©æåå¨ + æ¹æ¬¡ç®¡ç validateItemBatchManagement(reqVO.getReturnId(), reqVO.getItemId(), reqVO.getBatchId()); } /** * æ ¡éªåºåºè¡å½å±ä¸å¯éæ°éï¼å¹¶ä»åºåºè¡åå¡«ç©æãæ¹æ¬¡ */ private void validateOutboundLine(MesWmReturnSalesLineSaveReqVO reqVO, MesWmReturnSalesDO returnSales) { if (reqVO.getProductSalesLineId() == null) { throw exception(WM_RETURN_SALES_LINE_PRODUCT_SALES_REQUIRED); } MesWmProductSalesLineDO outboundLine = productSalesLineService.validateProductSalesLineExists(reqVO.getProductSalesLineId()); if (ObjUtil.notEqual(outboundLine.getSalesId(), returnSales.getProductSalesId())) { throw exception(WM_RETURN_SALES_LINE_PRODUCT_SALES_NOT_MATCH); } // ç©æãæ¹æ¬¡å¿ é¡»ä¸åºåºè¡ä¸è´ reqVO.setItemId(outboundLine.getItemId()); reqVO.setBatchId(outboundLine.getBatchId()); reqVO.setBatchCode(outboundLine.getBatchCode()); // å¯éæ°é = åºåºæ°é - å ¶å®éè´§å已鿰éï¼æé¤å½åéè´§åï¼ BigDecimal returned = getReturnedQuantityMap( Collections.singletonList(outboundLine.getId()), returnSales.getId()) .getOrDefault(outboundLine.getId(), BigDecimal.ZERO); BigDecimal returnable = outboundLine.getQuantity().subtract(returned); if (reqVO.getQuantity().compareTo(returnable) > 0) { throw exception(WM_RETURN_SALES_LINE_QUANTITY_EXCEED); } } @Override @@ -129,6 +172,16 @@ } @Override public Map<Long, BigDecimal> getReturnedQuantityMap(Collection<Long> productSalesLineIds, Long excludeReturnId) { if (CollUtil.isEmpty(productSalesLineIds)) { return Collections.emptyMap(); } List<KeyValue<Long, BigDecimal>> list = returnSalesLineMapper.selectReturnedQuantityList( productSalesLineIds, MesWmReturnSalesStatusEnum.CANCELED.getStatus(), excludeReturnId); return CollectionUtils.convertMap(list, KeyValue::getKey, KeyValue::getValue); } @Override public void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus) { List<MesWmReturnSalesLineDO> lines = returnSalesLineMapper.selectListByReturnId(returnId); for (MesWmReturnSalesLineDO line : lines) { @@ -155,7 +208,7 @@ * @param batchId æ¹æ¬¡ID */ private void validateItemBatchManagement(Long returnId, Long itemId, Long batchId) { MesMdmItemDO item = mdmItemService.validateItemExistsAndEnable(itemId); MdmItemRespDTO item = mdmItemApi.validateItemExistsAndEnable(itemId).getCheckedData(); // å¦æç©æå¯ç¨äºæ¹æ¬¡ç®¡çï¼åå¿ é¡»éæ©æ¹æ¬¡ if (Boolean.TRUE.equals(item.getIsBatchManaged()) && batchId == null) { throw exception(MD_ITEM_BATCH_REQUIRED); @@ -189,9 +242,11 @@ // 1.C.1 æ°å¢ä¸è¡ä¸åæ ¼å MesWmReturnSalesLineDO unqualifiedLine = new MesWmReturnSalesLineDO() .setReturnId(sourceLine.getReturnId()) .setProductSalesLineId(sourceLine.getProductSalesLineId()) .setItemId(sourceLine.getItemId()) .setQuantity(unqualifiedQuantity) .setBatchId(sourceLine.getBatchId()) .setBatchCode(sourceLine.getBatchCode()) .setRqcId(sourceLine.getRqcId()) .setRqcCheckFlag(sourceLine.getRqcCheckFlag()) .setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesService.java
@@ -1,10 +1,15 @@ package cn.iocoder.yudao.module.mes.service.wm.returnsales; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnableProductSalesLineRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; import jakarta.validation.Valid; import java.util.List; /** * MES éå®éè´§å Service æ¥å£ @@ -52,6 +57,22 @@ PageResult<MesWmReturnSalesDO> getReturnSalesPage(MesWmReturnSalesPageReqVO pageReqVO); /** * è·å¾å¯ééå®åºåºåå页ï¼ä» å·²å®æç¶æï¼ä¸åå¨å¯éæ°éå¤§äº 0 çè¡ * * @param pageReqVO å页忰 * @return éå®åºåºåå页 */ PageResult<MesWmProductSalesDO> getReturnableProductSalesPage(MesWmProductSalesPageReqVO pageReqVO); /** * è·å¾éå®åºåºåä¸ä»å¯éè´§çè¡å表 * * @param productSalesId éå®åºåºå ID * @return å¯éè¡å表 */ List<MesWmReturnableProductSalesLineRespVO> getReturnableProductSalesLineList(Long productSalesId); /** * æ ¡éªéå®éè´§åæ¯å¦åå¨ * * @param id ç¼å· yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
@@ -5,21 +5,30 @@ import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnableProductSalesLineRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesMapper; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi; import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; import jakarta.annotation.Resource; @@ -29,11 +38,14 @@ import java.math.BigDecimal; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** @@ -55,9 +67,15 @@ @Resource private CrmCustomerApi customerApi; @Resource private MesMdmItemService mdmItemService; private MdmItemApi mdmItemApi; @Resource private MdmUnitMeasureApi mdmUnitMeasureApi; @Resource private MesWmTransactionService wmTransactionService; @Resource private MesWmProductSalesMapper productSalesMapper; @Resource private MesWmProductSalesLineService productSalesLineService; @Override @Transactional(rollbackFor = Exception.class) @@ -76,9 +94,14 @@ @Transactional(rollbackFor = Exception.class) public void updateReturnSales(MesWmReturnSalesSaveReqVO updateReqVO) { // 1.1 æ ¡éªåå¨ + åå¤ä¸ç¶æ validateReturnSalesExistsAndPrepare(updateReqVO.getId()); MesWmReturnSalesDO oldReturnSales = validateReturnSalesExistsAndPrepare(updateReqVO.getId()); // 1.2 æ ¡éªå ³èæ°æ® validateSaveData(updateReqVO); // 1.3 å·²æéè´§è¡æ¶ï¼ä¸å è®¸æ´æ¢éå®åºåºå if (ObjUtil.notEqual(oldReturnSales.getProductSalesId(), updateReqVO.getProductSalesId()) && CollUtil.isNotEmpty(returnSalesLineService.getReturnSalesLineListByReturnId(updateReqVO.getId()))) { throw exception(WM_RETURN_SALES_PRODUCT_SALES_IMMUTABLE); } // 2. æ´æ°ä¸»è¡¨ MesWmReturnSalesDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDO.class); @@ -111,24 +134,113 @@ } @Override public PageResult<MesWmProductSalesDO> getReturnableProductSalesPage(MesWmProductSalesPageReqVO pageReqVO) { List<Long> permittedClientIds = customerApi.getPermittedCustomerIds(); return productSalesMapper.selectReturnablePage(pageReqVO, MesWmProductSalesStatusEnum.FINISHED.getStatus(), MesWmReturnSalesStatusEnum.CANCELED.getStatus(), permittedClientIds); } @Override public List<MesWmReturnableProductSalesLineRespVO> getReturnableProductSalesLineList(Long productSalesId) { if (productSalesId == null) { return Collections.emptyList(); } MesWmProductSalesDO productSales = productSalesMapper.selectById(productSalesId); if (productSales == null) { throw exception(WM_RETURN_SALES_PRODUCT_SALES_NOT_EXISTS); } List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(productSalesId); if (CollUtil.isEmpty(lines)) { return Collections.emptyList(); } Map<Long, BigDecimal> returnedMap = returnSalesLineService.getReturnedQuantityMap( convertList(lines, MesWmProductSalesLineDO::getId), null); // ä» ä¿çå¯éæ°éå¤§äº 0 çåºåºè¡ List<MesWmProductSalesLineDO> returnableLines = lines.stream() .filter(line -> line.getQuantity() != null && line.getQuantity().subtract(returnedMap.getOrDefault(line.getId(), BigDecimal.ZERO)) .compareTo(BigDecimal.ZERO) > 0) .toList(); if (CollUtil.isEmpty(returnableLines)) { return Collections.emptyList(); } Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( convertSet(returnableLines, MesWmProductSalesLineDO::getItemId)); Map<Long, MdmUnitMeasureRespDTO> unitMap = CollectionUtils.convertMap( mdmUnitMeasureApi.getUnitMeasureList(convertSet(itemMap.values(), MdmItemRespDTO::getUnitMeasureId)) .getCheckedData(), MdmUnitMeasureRespDTO::getId); return returnableLines.stream().map(line -> { MesWmReturnableProductSalesLineRespVO vo = new MesWmReturnableProductSalesLineRespVO(); BigDecimal returned = returnedMap.getOrDefault(line.getId(), BigDecimal.ZERO); vo.setProductSalesLineId(line.getId()); vo.setSalesId(line.getSalesId()); vo.setItemId(line.getItemId()); vo.setBatchId(line.getBatchId()); vo.setBatchCode(line.getBatchCode()); vo.setOutboundQuantity(line.getQuantity()); vo.setReturnedQuantity(returned); vo.setReturnableQuantity(line.getQuantity().subtract(returned)); MapUtils.findAndThen(itemMap, line.getItemId(), item -> { vo.setItemCode(item.getCode()); vo.setItemName(item.getName()); vo.setItemSpecification(item.getSpecification()); MapUtils.findAndThen(unitMap, item.getUnitMeasureId(), unit -> vo.setItemUnit(unit.getName())); }); return vo; }).toList(); } @Override @Transactional(rollbackFor = Exception.class) public void submitReturnSales(Long id) { // 1.1 æ ¡éªåå¨ + èç¨¿ç¶æ validateReturnSalesExistsAndPrepare(id); MesWmReturnSalesDO returnSales = validateReturnSalesExistsAndPrepare(id); // 1.2 æ ¡éªè³å°æä¸æ¡è¡ List<MesWmReturnSalesLineDO> lines = returnSalesLineService.getReturnSalesLineListByReturnId(id); if (CollUtil.isEmpty(lines)) { throw exception(WM_RETURN_SALES_NO_LINE); } // 1.3 å ³èåºå®åºåæ¶ï¼éæ°æ ¡éªè¡å½å±ä¸å¯éæ°éï¼è稿æé´å¯è½å·²è¢«å ¶å®éè´§åå ç¨ï¼ if (returnSales.getProductSalesId() != null) { validateLinesAgainstProductSales(returnSales, lines); } // 2.1 ç¡®å®ç®æ ç¶æï¼1ï¼æå¾ æ£éªç©æ â å¾ æ£éªç¶æï¼2ï¼æ å¾ æ£éªç©æ â å¾ æ§è¡ç¶æ boolean hasPendingQc = CollUtil.contains(lines, line -> MesWmQualityStatusEnum.PENDING.getStatus().equals(line.getQualityStatus())); Integer targetStatus = hasPendingQc ? MesWmReturnSalesStatusEnum.CONFIRMED.getStatus() : MesWmReturnSalesStatusEnum.APPROVING.getStatus(); // 2.2 æäº¤ï¼è稿 -> å¾ æ£éª/å¾ æ§è¡ï¼ // 2. æäº¤ï¼è稿 -> å¾ æ§è¡ï¼ï¼éå®ä»åºæµè½¬ä¸ç»è¿è´¨æ£ returnSalesMapper.updateById(new MesWmReturnSalesDO() .setId(id).setStatus(targetStatus)); .setId(id).setStatus(MesWmReturnSalesStatusEnum.APPROVING.getStatus())); } /** * æ ¡éªéè´§åææè¡åæ¥èªæéçéå®åºåºåï¼ä¸æ¬ååè¡æ°éä¹åä¸è¶ è¿å¯éæ°é */ private void validateLinesAgainstProductSales(MesWmReturnSalesDO returnSales, List<MesWmReturnSalesLineDO> lines) { if (CollUtil.contains(lines, line -> line.getProductSalesLineId() == null)) { throw exception(WM_RETURN_SALES_LINE_PRODUCT_SALES_REQUIRED); } Map<Long, MesWmProductSalesLineDO> outboundLineMap = convertMap( productSalesLineService.getProductSalesLineListBySalesId(returnSales.getProductSalesId()), MesWmProductSalesLineDO::getId); // æ±æ»æ¬åæ¯ä¸ªåºåºè¡çéè´§æ°é Map<Long, BigDecimal> lineQuantityMap = new HashMap<>(); for (MesWmReturnSalesLineDO line : lines) { if (!outboundLineMap.containsKey(line.getProductSalesLineId())) { throw exception(WM_RETURN_SALES_LINE_PRODUCT_SALES_NOT_MATCH); } lineQuantityMap.merge(line.getProductSalesLineId(), line.getQuantity(), BigDecimal::add); } // 已鿰éæé¤æ¬åï¼é¿å ææ¬åèªèº«è®¡å ¥ Map<Long, BigDecimal> returnedMap = returnSalesLineService.getReturnedQuantityMap( convertSet(lines, MesWmReturnSalesLineDO::getProductSalesLineId), returnSales.getId()); for (Map.Entry<Long, BigDecimal> entry : lineQuantityMap.entrySet()) { BigDecimal returnable = outboundLineMap.get(entry.getKey()).getQuantity() .subtract(returnedMap.getOrDefault(entry.getKey(), BigDecimal.ZERO)); if (entry.getValue().compareTo(returnable) > 0) { throw exception(WM_RETURN_SALES_LINE_QUANTITY_EXCEED); } } } @Override @@ -171,7 +283,7 @@ MesWmReturnSalesDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); // 对æ¯è¡æ°éä¸æç»æ»æ°éï¼ä¸æ»¡è¶³ç´æ¥æåº if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { MesMdmItemDO item = mdmItemService.validateItemExistsAndEnable(line.getItemId()); MdmItemRespDTO item = mdmItemApi.validateItemExistsAndEnable(line.getItemId()).getCheckedData(); throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_MISMATCH, item.getCode() + " " + item.getName() + " æªå®æä¸æ¶"); } @@ -188,13 +300,24 @@ private void createTransactionList(MesWmReturnSalesDO returnSales) { List<MesWmReturnSalesDetailDO> details = returnSalesDetailService.getReturnSalesDetailListByReturnId(returnSales.getId()); wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) .setQuantity(detail.getQuantity()) // å ¥åºæ°éä¸ºæ£æ° .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) .setBizType(MesBizTypeConstants.WM_RETURN_SALES).setBizId(returnSales.getId()) .setBizCode(returnSales.getCode()).setBizLineId(detail.getLineId()))); // æç»æªå¸¦æ¹æ¬¡æ¶åéå°éè´§è¡æ¹æ¬¡ï¼é¿å å岿°æ®å ¥åºä¸¢æ¹æ¬¡ Map<Long, MesWmReturnSalesLineDO> lineMap = convertMap( returnSalesLineService.getReturnSalesLineListByReturnId(returnSales.getId()), MesWmReturnSalesLineDO::getId); wmTransactionService.createTransactionList(convertList(details, detail -> { MesWmReturnSalesLineDO line = lineMap.get(detail.getLineId()); Long batchId = detail.getBatchId() != null ? detail.getBatchId() : line != null ? line.getBatchId() : null; String batchCode = detail.getBatchCode() != null ? detail.getBatchCode() : line != null ? line.getBatchCode() : null; return new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) .setQuantity(detail.getQuantity()) // å ¥åºæ°éä¸ºæ£æ° .setBatchId(batchId).setBatchCode(batchCode) .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) .setBizType(MesBizTypeConstants.WM_RETURN_SALES).setBizId(returnSales.getId()) .setBizCode(returnSales.getCode()).setBizLineId(detail.getLineId()); })); } @Override @@ -274,6 +397,21 @@ private void validateSaveData(MesWmReturnSalesSaveReqVO reqVO) { validateCodeUnique(reqVO.getId(), reqVO.getCode()); customerApi.validateCustomer(reqVO.getClientId()); // å ³èéå®åºåºåæ¶ï¼æ ¡éªåºåºåç¶æä¸å®¢æ·ä¸è´æ§ï¼å¹¶åå¡«åºåºåå· if (reqVO.getProductSalesId() == null) { return; } MesWmProductSalesDO productSales = productSalesMapper.selectById(reqVO.getProductSalesId()); if (productSales == null) { throw exception(WM_RETURN_SALES_PRODUCT_SALES_NOT_EXISTS); } if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.FINISHED.getStatus(), productSales.getStatus())) { throw exception(WM_RETURN_SALES_PRODUCT_SALES_NOT_FINISHED); } if (ObjUtil.notEqual(productSales.getClientId(), reqVO.getClientId())) { throw exception(WM_RETURN_SALES_CLIENT_MISMATCH); } reqVO.setProductSalesCode(productSales.getCode()); } } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java
@@ -308,7 +308,6 @@ salesLine.setQuantity(noticeLine.getQuantity()); salesLine.setBatchId(noticeLine.getBatchId()); salesLine.setBatchCode(noticeLine.getBatchCode()); salesLine.setOqcCheckFlag(noticeLine.getOqcCheckFlag()); productSalesLineMapper.insert(salesLine); }