refactor(mes): 重构质量管理和批次绑定功能
- 移除 mes_qc_oqc_action 表及相关实体类和映射器
- 删除 workflow_status 字段和相关查询条件
- 新增 mes_qc_approver_config 表用于质检审核人配置
- 添加新的错误码常量用于质检审核配置验证
- 更新种子质量工作流状态定义和菜单权限配置
- 移除物料名称唯一性校验相关代码和错误码
- 新增获取未绑定批次吨袋的功能接口
- 实现批次绑定模式检查和吨袋绑定逻辑
- 优化批次状态变更和绑定托盘吨袋处理流程
已添加24个文件
已删除4个文件
已修改33个文件
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active] [ref=e4]: |
| | | - generic [ref=e201]: |
| | | - complementary [ref=e203]: |
| | | - generic [ref=e204]: |
| | | - generic [ref=e205] [cursor=pointer] |
| | | - link "å·¥ä¸AIæºé å¹³å° å·¥ä¸AIæºé å¹³å°" [ref=e210] [cursor=pointer]: |
| | | - /url: javascript:void 0 |
| | | - img "å·¥ä¸AIæºé å¹³å°" [ref=e213] |
| | | - generic [ref=e214]: å·¥ä¸AIæºé å¹³å° |
| | | - menu [ref=e217]: |
| | | - menuitem "é¦é¡µ" [ref=e218] [cursor=pointer] |
| | | - listitem [ref=e222]: |
| | | - generic [ref=e223] [cursor=pointer]: åºç¡æ°æ® |
| | | - listitem [ref=e228]: |
| | | - generic [ref=e229] [cursor=pointer]: ç»éå管ç |
| | | - listitem [ref=e234]: |
| | | - generic [ref=e235] [cursor=pointer]: ä»å¨ç©æµ |
| | | - listitem [ref=e240]: |
| | | - generic [ref=e241] [cursor=pointer]: åºåºæµé管ç |
| | | - listitem [ref=e246]: |
| | | - generic [ref=e247] [cursor=pointer]: é²ä¼ªé²çªè´§ç®¡ç |
| | | - listitem [ref=e252]: |
| | | - generic [ref=e253] [cursor=pointer]: 溯æºåæ |
| | | - listitem [ref=e258]: |
| | | - generic [ref=e259] [cursor=pointer]: ä¸è¢ä¸ç 管ç |
| | | - listitem [ref=e264]: |
| | | - generic [ref=e265] [cursor=pointer]: è´¨é管ç |
| | | - listitem [ref=e270]: |
| | | - generic [ref=e271] [cursor=pointer]: ç»è®¡åæ |
| | | - listitem [ref=e276]: |
| | | - generic [ref=e277] [cursor=pointer]: ç³»ç»ç®¡ç |
| | | - generic [ref=e283] [cursor=pointer] |
| | | - generic [ref=e288]: |
| | | - generic [ref=e289]: |
| | | - banner [ref=e290]: |
| | | - button [ref=e291] [cursor=pointer] |
| | | - button [ref=e293] [cursor=pointer] |
| | | - navigation "breadcrumb" [ref=e298]: |
| | | - list [ref=e299]: |
| | | - listitem [ref=e300]: |
| | | - link "é¦é¡µ" [disabled] [ref=e301] |
| | | - generic [ref=e305]: |
| | | - generic [ref=e307] [cursor=pointer]: |
| | | - generic [ref=e311]: æç´¢ |
| | | - generic [ref=e312]: Ctrl K |
| | | - button [ref=e314] [cursor=pointer] |
| | | - button "dark" [ref=e319] [cursor=pointer] |
| | | - button [ref=e328] [cursor=pointer] |
| | | - button [ref=e334] [cursor=pointer] |
| | | - button [ref=e336] [cursor=pointer] |
| | | - button [ref=e342] [cursor=pointer]: |
| | | - button [ref=e344] |
| | | - button "å·¥ä½å°" [ref=e348] [cursor=pointer] |
| | | - button [ref=e351] [cursor=pointer]: |
| | | - img "è¶
级管çå" [ref=e356] |
| | | - generic [ref=e358]: |
| | | - generic [ref=e359]: é¦é¡µ |
| | | - generic [ref=e377]: |
| | | - button [ref=e378] [cursor=pointer] |
| | | - generic [ref=e385] [cursor=pointer] |
| | | - generic [ref=e389] [cursor=pointer] |
| | | - main [ref=e396]: |
| | | - generic [ref=e400]: |
| | | - generic [ref=e401]: |
| | | - generic [ref=e402]: ä¸å¡å
¨é¾è·¯ |
| | | - generic [ref=e408]: |
| | | - generic [ref=e412] [cursor=pointer]: |
| | | - generic [ref=e413]: åç§ |
| | | - generic [ref=e414]: "0" |
| | | - generic [ref=e420] [cursor=pointer]: |
| | | - generic [ref=e421]: 产线 |
| | | - generic [ref=e422]: "0" |
| | | - generic [ref=e428] [cursor=pointer]: |
| | | - generic [ref=e429]: çäº§æ¹æ¬¡ |
| | | - generic [ref=e430]: "0" |
| | | - generic [ref=e436] [cursor=pointer]: |
| | | - generic [ref=e437]: è¢ç |
| | | - generic [ref=e438]: "0" |
| | | - generic [ref=e444] [cursor=pointer]: |
| | | - generic [ref=e445]: æçç |
| | | - generic [ref=e446]: "0" |
| | | - generic [ref=e452] [cursor=pointer]: |
| | | - generic [ref=e453]: éå®åºåº |
| | | - generic [ref=e454]: "0" |
| | | - generic [ref=e460] [cursor=pointer]: |
| | | - generic [ref=e461]: æµéæ«ç |
| | | - generic [ref=e462]: "0" |
| | | - generic [ref=e468] [cursor=pointer]: |
| | | - generic [ref=e469]: é²çª/æº¯æº |
| | | - generic [ref=e470]: "0" |
| | | - generic [ref=e471]: |
| | | - generic [ref=e478] [cursor=pointer]: |
| | | - generic [ref=e479]: åç§æ»æ° |
| | | - generic [ref=e480]: "0" |
| | | - generic [ref=e481]: åºç¡æ°æ® |
| | | - generic [ref=e488] [cursor=pointer]: |
| | | - generic [ref=e489]: çäº§æ¹æ¬¡ |
| | | - generic [ref=e490]: "0" |
| | | - generic [ref=e491]: ä¸è¢ä¸ç |
| | | - generic [ref=e498] [cursor=pointer]: |
| | | - generic [ref=e499]: è¢ç |
| | | - generic [ref=e500]: "0" |
| | | - generic [ref=e501]: èµç |
| | | - generic [ref=e508] [cursor=pointer]: |
| | | - generic [ref=e509]: æçç |
| | | - generic [ref=e510]: "0" |
| | | - generic [ref=e511]: æç |
| | | - generic [ref=e518] [cursor=pointer]: |
| | | - generic [ref=e519]: éå®åºåºå |
| | | - generic [ref=e520]: "0" |
| | | - generic [ref=e521]: åºåºæµé |
| | | - generic [ref=e528] [cursor=pointer]: |
| | | - generic [ref=e529]: 累计æ«ç |
| | | - generic [ref=e530]: "0" |
| | | - generic [ref=e531]: æº¯æº |
| | | - generic [ref=e538] [cursor=pointer]: |
| | | - generic [ref=e539]: åºåé¢è¦ |
| | | - generic [ref=e540]: "0" |
| | | - generic [ref=e541]: ä»å¨ |
| | | - generic [ref=e548] [cursor=pointer]: |
| | | - generic [ref=e549]: å¾
è¯å®¡ä¸åæ ¼ |
| | | - generic [ref=e550]: "0" |
| | | - generic [ref=e551]: è´¨é |
| | | - generic [ref=e552]: |
| | | - generic [ref=e556]: |
| | | - generic [ref=e557]: è¢ç çæè¶å¿ |
| | | - generic [ref=e559]: |
| | | - generic [ref=e560] [cursor=pointer]: |
| | | - generic [ref=e561]: |
| | | - radio "è¿ 7 天" [checked] |
| | | - generic [ref=e562]: è¿ 7 天 |
| | | - generic [ref=e563] [cursor=pointer]: |
| | | - generic [ref=e564]: |
| | | - radio "è¿ 30 天" |
| | | - generic [ref=e565]: è¿ 30 天 |
| | | - generic [ref=e568]: æ¶è´¹è
æ«ç å°åºåå¸ |
| | | - generic [ref=e577]: |
| | | - generic [ref=e578]: æ¹æ¬¡ç¶æåå¸ |
| | | - generic [ref=e585]: è¢ç ç¶æåå¸ |
| | | - generic [ref=e593]: |
| | | - generic [ref=e594]: å¾
åä¸é¢è¦ |
| | | - generic [ref=e598]: |
| | | - generic [ref=e602] [cursor=pointer]: |
| | | - generic [ref=e603]: çªè´§é¢è¦ |
| | | - generic [ref=e604]: å¾
å¤çççªè´§é¢è¦ |
| | | - generic [ref=e608] [cursor=pointer]: |
| | | - generic [ref=e609]: åºåé¢è¦ |
| | | - generic [ref=e610]: æªå¤ççåºåé¢è¦ |
| | | - generic [ref=e614] [cursor=pointer]: |
| | | - generic [ref=e615]: ä¸åæ ¼å |
| | | - generic [ref=e616]: å¾
è¯å®¡çä¸åæ ¼åå |
| | | - generic [ref=e617]: |
| | | - generic [ref=e618]: å¿«æ·å
¥å£ |
| | | - generic [ref=e622]: |
| | | - generic [ref=e624]: |
| | | - generic [ref=e625]: åºç¡æ°æ® |
| | | - generic [ref=e626]: |
| | | - generic [ref=e627] [cursor=pointer]: åç§ç®¡ç |
| | | - generic [ref=e630] [cursor=pointer]: åç§åç±» |
| | | - generic [ref=e633] [cursor=pointer]: 计éåä½ |
| | | - generic [ref=e637]: |
| | | - generic [ref=e638]: ä¸è¢ä¸ç ç产 |
| | | - generic [ref=e639]: |
| | | - generic [ref=e640] [cursor=pointer]: äº§çº¿ç»´æ¤ |
| | | - generic [ref=e643] [cursor=pointer]: æ¹æ¬¡ç产 |
| | | - generic [ref=e646] [cursor=pointer]: èµç 管ç |
| | | - generic [ref=e649] [cursor=pointer]: æçç |
| | | - generic [ref=e652] [cursor=pointer]: æ«ç å
¥åº |
| | | - generic [ref=e656]: |
| | | - generic [ref=e657]: åºåºæµé |
| | | - generic [ref=e658]: |
| | | - generic [ref=e659] [cursor=pointer]: åè´§éç¥ |
| | | - generic [ref=e662] [cursor=pointer]: éå®åºåº |
| | | - generic [ref=e665] [cursor=pointer]: éå®éè´§ |
| | | - generic [ref=e669]: |
| | | - generic [ref=e670]: é²ä¼ªé²çªè´§ |
| | | - generic [ref=e671]: |
| | | - generic [ref=e672] [cursor=pointer]: çªè´§é¢è¦ |
| | | - generic [ref=e675] [cursor=pointer]: æ«ç å°çåå¸ |
| | | - generic [ref=e678] [cursor=pointer]: 宿´æ§æ ¡éª |
| | | - generic [ref=e682]: |
| | | - generic [ref=e683]: 溯æºåæ |
| | | - generic [ref=e684]: æ¶è´¹è
æ«ç ç»è®¡ |
| | | - generic [ref=e689]: |
| | | - generic [ref=e690]: ä»å¨ç©æµ |
| | | - generic [ref=e691]: |
| | | - generic [ref=e692] [cursor=pointer]: ä»åºè®¾ç½® |
| | | - generic [ref=e695] [cursor=pointer]: åºåç°æé |
| | | - generic [ref=e698] [cursor=pointer]: åºåé¢è¦ |
| | | - generic [ref=e701] [cursor=pointer]: è½¬ç§»è°æ¨ |
| | | - generic [ref=e705]: |
| | | - generic [ref=e706]: è´¨é管ç |
| | | - generic [ref=e707]: |
| | | - generic [ref=e708] [cursor=pointer]: æ¹æ¬¡è¿½æº¯ |
| | | - generic [ref=e711] [cursor=pointer]: ä¸åæ ¼å |
| | | - generic [ref=e714] [cursor=pointer]: ç§åè´¨æ£ |
| | | - generic [ref=e719]: |
| | | - generic [ref=e721]: |
| | | - img "check-circle" [ref=e722] |
| | | - generic [ref=e726]: ç»å½æå |
| | | - generic [ref=e727]: 欢è¿åæ¥:è¶
级管çå |
| | | - img "close" [ref=e730] [cursor=pointer] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| | |
| | | # çäº§è´¨æ£æµç¨ä¸èåæ å° |
| | | # ç§åè´¨æ£æµç¨ |
| | | |
| | | 便®ç¨æ·æä¾çç产æµç¨å¾åå½å `system_menu`ï¼ä¿çå·²æè´¨é管çèåï¼æ°å¢âéå®è´¨æ£âå
¥å£ã |
| | | æè¢ç ä¿åè´¨æ£è®°å½ï¼æçç ãæ¹æ¬¡ç æäº¤æ¶ï¼æ¯è¢çæç¬ç«è®°å½ã纯度ãå度ãåè½çãæ°´ååé¡¹ææ å¨åæ£ã鿰忣å夿£ä¸ä¸è´ãæ¯æ¬¡æ£éªä¿åææ å¿«ç
§ãæä½äººãæ¶é´åä¸åæ ¼åå ã |
| | | |
| | | | æµç¨å¾èç¹ | ç³»ç»å
¥å£ | å®ç° | |
| | | è´¨æ£é¡¹åæ ¼èå´é
置页维æ¤åé¡¹ææ çé»è®¤ç¾åæ¯ä¸ä¸éï¼å«è¾¹çï¼ãè¿æ¯å¡«å模æ¿ï¼æªé
ç½®æ¶å¯æå¨å¡«åï¼åæ£ã鿰忣å夿£åå¯ä¿®æ¹æ¬æ¬¡èå´ãæå¡ç«¯ææ¬æ¬¡æäº¤ç宿µå¼åèå´å¤å®ï¼å¹¶ä¿åèå´å¿«ç
§ï¼é
ç½®æ´æ°ä¸æ¹ååå²è®°å½ãæ¡é¢ç«¯åæµè§å¨ç§»å¨ç«¯å坿«ææçç æçäº§æ¹æ¬¡ç ï¼æ¹éå¤ç该èå´å
åä¸å¾
æ£ç¶æçå
¨é¨è¢ç ï¼æäº¤æ¶éæ°æ ¸å¯¹æ¸
åï¼ä»»ä¸è¢å¤±è´¥åæ´æ¹åæ»ã |
| | | |
| | | | ç¶æ | è¿å
¥æ¡ä»¶ | ä¸ä¸æ¥ | |
| | | | --- | --- | --- | |
| | | | 48/100 è¢æ«ç å
¥åºãçææçç | ä¸è¢ä¸ç / ä»å¨ç©æµ | æ¢æè¢ç ãæçç ãæ¹æ¬¡ç | |
| | | | å å·¥é¨åæ£ | è´¨é管ç / ç§åè´¨æ£ | 坿è¢ãæçãæ¹æ¬¡æäº¤ï¼æ¯è¢ç¬ç«è®°å½ | |
| | | | 忣ä¸åæ ¼ã夿£ | è´¨é管ç / è´¨æ£è®°å½ | ä¿çæååºåï¼è®°å½å¤æ£ç»æä¸åæ¬¡ææ | |
| | | | å å·¥é¨é¢å¯¼å®¡æ¹ | è´¨é管ç / è´¨æ£è®°å½ | åæ¡æåç¶ææ¹é审æ¹ï¼å¯é©³å鿣 | |
| | | | å
¬å¸è´¨æ£å®¡æ¹ | è´¨é管ç / è´¨æ£è®°å½ | åæ¡æåç¶ææ¹é审æ¹ï¼éè¿åæè¿ç§»ææ¥åºåºå | |
| | | | éå®é¨è´¨æ£ | è´¨é管ç / éå®è´¨æ£ | ç¬ç«èåï¼å¤ç¨æ¢æ OQC éå®åºåºåæ£éªå | |
| | | | éå®å¤æ£ä¸å®¡æ¹ | è´¨é管ç / éå®è´¨æ£ | ä¸åæ ¼å
夿£ï¼éå®é¨ä¸å
¬å¸è´¨æ£å®¡æ¹ååååºåºè´¨éç¶æ | |
| | | | ä¸åæ ¼åççè¯å®¡ | è´¨é管ç / ä¸åæ ¼åå¤ç | æ¢æ OQC/IPQC èªå¨å建 NCR | |
| | | | æ£å¼å
¥åºãåºåºãæ«ç 追溯 | ä»å¨ç©æµ / åºåºæµé / 追溯 | å®¡æ¹æ¾è¡åè¢ç `qc_status=20`ï¼æªæ¾è¡ä¸è½æ«ç åºåº | |
| | | | 20 å¾
åæ£å®¡æ ¸ | åæ£åæ ¼ | éè¿ â 10ï¼é©³å â 50 | |
| | | | 25 å¾
忣ä¸åæ ¼å¤ç | 忣ä¸åæ ¼ | ç¡®è®¤å¹¶å®æå¤æ£ â 10ï¼é©³ååæ£éª â 50 | |
| | | | 50 忣驳åå¾
鿣 | åæ£å®¡æ ¸é©³å | éæ°å½å
¥åé¡¹ææ â 20 æ 25 | |
| | | | 10 å¾
夿£ | åæ£å®¡æ ¸éè¿ï¼æå¤æ£å®¡æ ¸é©³å | å½å
¥åé¡¹ææ â 30 æ 60 | |
| | | | 30 å¾
夿£å®¡æ ¸ | 夿£åæ ¼ | éè¿ â 40ï¼é©³å â 10 | |
| | | | 60 å¾
夿£ä¸åæ ¼å¤ç | 夿£ä¸åæ ¼ | 确认æ¥åº â 70ï¼é©³å鿰夿£ â 10 | |
| | | | 40 å·²æ¾è¡ | 夿£åæ ¼ä¸å®¡æ ¸éè¿ | è¢ç 转å
¥éå®åæ ¼åº | |
| | | | 70 å·²æ¥åº | 夿£ä¸åæ ¼ä¸å®¡æ ¸ç¡®è®¤ | æååºåæ£åå¹¶æ¥åºè¢ç | |
| | | |
| | | ## ç§åè´¨æ£ç¶æ |
| | | 忣ä¸å¤æ£æé´åºåç卿ååºãåªææç»å®¡æ ¸éè¿æåçåºåäºå¡ãä¸åæ ¼æ£éªå¿
须填ååå ï¼å¤ç½®äººéå¡«åå®¡æ ¸æè§ã夿£ä¸åæ ¼ç¡®è®¤æ¶æç¡®æ§è¡æ¥åºï¼é©³ååéå夿£ãæ¹éå®¡æ ¸å¨åä¸äºå¡å
宿ï¼ä»»ä¸è¢åºåæµè½¬å¤±è´¥åå
¨é¨åæ»ã |
| | | |
| | | - 10 å¾
夿£ï¼åæ£å¤±è´¥æå®¡æ¹é©³åï¼åºåä»å¨æååºã |
| | | - 20 å¾
å å·¥é¨å®¡æ¹ï¼åæ£æå¤æ£åæ ¼ã |
| | | - 30 å¾
å
¬å¸è´¨æ£å®¡æ¹ï¼å å·¥é¨åææ¾è¡ã |
| | | - 40 å·²æ¾è¡ï¼å
¬å¸è´¨æ£åæï¼äºå¡æ§å°å°è¯¥è¢ç±æååºç§»å
¥åæ ¼åºã |
| | | - 50 å¾
å å·¥é¨ä¸åæ ¼è¯å®¡ï¼å¤æ£ä¸åæ ¼ã |
| | | - 60 å¾
å
¬å¸ä¸åæ ¼å®¡æ¹ï¼å å·¥é¨åææ¥åºã |
| | | - 70 å·²æ¥åºï¼å
¬å¸è´¨æ£åæï¼äºå¡æ§å°ç§»é¤è¯¥è¢æååºåã |
| | | âè´¨æ£å®¡æ ¸äººé
ç½®âä»
ç»´æ¤ç§åè´¨æ£çåæ£å®¡æ ¸ï¼èç¹ 1ï¼å夿£å®¡æ ¸ï¼èç¹ 3ï¼ï¼æ¯æå¤äººååç¨ãæå¡ç«¯åæ¶æ ¡éªæé®æéä¸å½åå®¡æ ¸äººé
ç½®ï¼è¶
级管çåå¯è·³è¿å®¡æ ¸äººé
ç½®æ ¡éªãå process-approve / company-approve æ¥å£åæéç ä¿çï¼å
¼å®¹å·²åé
è§è²ã |
| | | |
| | | 审æ¹é©³ååå° 10ãæ¯æ¬¡åæ£ã夿£å审æ¹åå
¥ `mes_qc_seed_quality_action`ï¼å
嫿ä½äººãæ¶é´ãæè§åæ£éªææ å¿«ç
§ãæ¹é审æ¹å¨å䏿°æ®åºäºå¡å
æ§è¡ï¼ä»»ä¸è¢åºåæµè½¬å¤±è´¥åå
¨é¨åæ»ã |
| | | ## é¨ç½² |
| | | |
| | | éå®è´¨æ£çæµç¨ç¶æä¸ç§åè´¨æ£ç¸åï¼å
¶ä¸ 20/50 ç±éå®é¨å®¡æ¹ï¼40 表示åºè´§æ£éªéè¿å¹¶ååéå®åºåºåè¡ï¼70 表示ä¸åæ ¼å®¡æ¹å®æå¹¶åå为ä¸åæ ¼ï¼åæ¶å建 NCRã忣ä¸å¤æ£ä¸åååºåºåè´¨éç»æï¼å æ¤å®¡æ¹åä»å¤äºå¾
æ£ç¶æã夿£ååæ°éåå®¡æ¹æè§åå
¥ `mes_qc_oqc_action`ã |
| | | |
| | | ## é¨ç½²é¡ºåº |
| | | |
| | | 1. å¤ä»½æ°æ®åºï¼æ§è¡ `sql/mysql/mes_seed_quality_workflow_20261019.sql`ãèæ¬æ¯ä¸æ¬¡æ§è¿ç§»ï¼åå²å·²æµè½¬çåæ ¼/ä¸åæ ¼è®°å½å嫿 记为 40/70ï¼é¿å
éå¤åºåäºå¡ã |
| | | 2. é¨ç½²å端ãå端ãå端æå»ºäº§ç©å¨ `mom-pro2-before/dist.zip`ã |
| | | 3. 为å å·¥é¨ä¸å
¬å¸è´¨æ£è§è²åå«æäº `mes:qc-seed-quality:process-approve`ã`mes:qc-seed-quality:company-approve`ï¼å¤æ£äººåæäº `mes:qc-seed-quality:retest`ã为éå®é¨ä¸å
¬å¸è´¨æ£è§è²åå«æäº `mes:qc-oqc:sales-approve`ã`mes:qc-oqc:company-approve`ï¼éå®å¤æ£äººåæäº `mes:qc-oqc:retest`ãæ ¸å¯¹âéå®è´¨æ£âèåè§è²æéã |
| | | |
| | | âéå®è´¨æ£âä¸åâåºè´§æ£éªâå
±ç¨ OQC æ£éªå忢æåºè´§æ£éªè¡¨åï¼ä½æç¬ç«èåä¸ä¸é¨ç夿£ãå®¡æ¹æä½ãåâè¿ç¨æ£éªï¼IPQCï¼â仿å¡ç产任å¡åæ¥å·¥ï¼æªå¹¶å
¥æè¢ç æµè½¬çç§åè´¨æ£å®¡æ¹é¾ã |
| | | 1. å¤ä»½æ°æ®åºï¼æ§è¡ sql/mysql/mes_seed_quality_workflow_20261019.sqlãåå²å·²æµè½¬è®°å½æ 为已æ¾è¡æå·²æ¥åºï¼é¿å
éå¤åºåäºå¡ã |
| | | 2. æ§è¡ sql/mysql/mes_qc_oqc_retest_approver_20261019.sqlï¼åå»ºå®¡æ ¸äººé
ç½®ä¸èåãè¯¥èæ¬ä»
æ¶åç§åè´¨æ£ï¼ä¸ä¿®æ¹å
¶ä»è´¨æ£è¡¨ã |
| | | 3. æ§è¡ sql/mysql/mes_qc_seed_indicator_range_20261019.sqlï¼å建èå´æ¨¡æ¿è¡¨å页é¢èåï¼ä¸ºç®¡çååé
mes:qc-seed-range:queryãmes:qc-seed-range:update æéã建议é
ç½®å®æ´å项é»è®¤èå´ã |
| | | 4. é¨ç½²å端å mom-pro2-before å端ãåé
mes:qc-seed-quality:retestãmes:qc-seed-quality:process-approveãmes:qc-seed-quality:company-approve æéï¼å¹¶å¨å®¡æ ¸äººé
ç½®ä¸æå®ä¸¤èç¹å®¡æ ¸äººã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- è´¨æ£å®¡æ ¸äººé
ç½®ï¼ä»
ç§åè´¨æ£ï¼æåæ£å®¡æ ¸/夿£å®¡æ ¸èç¹ç»´æ¤ï¼å¯é
ç½®å¤äººã |
| | | CREATE TABLE IF NOT EXISTS mes_qc_approver_config ( |
| | | id bigint NOT NULL AUTO_INCREMENT, |
| | | qc_type tinyint NOT NULL COMMENT 'è´¨æ£ç±»åï¼1ç§åè´¨æ£', |
| | | approve_node tinyint NOT NULL COMMENT 'å®¡æ ¸èç¹ï¼1åæ£å®¡æ ¸ 3夿£å®¡æ ¸', |
| | | user_id bigint NOT NULL COMMENT 'å®¡æ ¸äººç¨æ·ID', |
| | | status tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0å¯ç¨ 1åç¨', |
| | | remark varchar(255) DEFAULT NULL COMMENT '夿³¨', |
| | | creator varchar(64) DEFAULT '', |
| | | create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | updater varchar(64) DEFAULT '', |
| | | update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
| | | deleted bit(1) NOT NULL DEFAULT b'0', |
| | | PRIMARY KEY (id), |
| | | KEY idx_qc_type_node (qc_type, approve_node) |
| | | ) ENGINE=InnoDB COMMENT='è´¨æ£å®¡æ ¸äººé
ç½®'; |
| | | |
| | | -- è´¨é管ç / è´¨æ£å®¡æ ¸äºº èååæé®æé |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'è´¨æ£å®¡æ ¸äºº', '', 2, 9, 5500, 'approver-config', 'ep:user', 'mes/qc/approverConfig/index', 'MesQcApproverConfig', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM system_menu WHERE parent_id = 5500 AND path = 'approver-config' AND deleted = b'0'); |
| | | |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'æ¥è¯¢', 'mes:qc-approver:query', 3, 1, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'approver-config' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-approver:query' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'æ°å¢', 'mes:qc-approver:create', 3, 2, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'approver-config' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-approver:create' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'ä¿®æ¹', 'mes:qc-approver:update', 3, 3, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'approver-config' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-approver:update' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'å é¤', 'mes:qc-approver:delete', 3, 4, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'approver-config' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-approver:delete' AND m.deleted = b'0'); |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ä¸çº¿éå®è´¨æ£ä¸å¡çº¿ï¼é»è¾å é¤âéå®è´¨æ£âèååæé®æéï¼æ¸
çéå®è´¨æ£å®¡æ ¸äººé
ç½®ã |
| | | -- åºè´§æ£éªï¼OQCï¼åºç¡åè½ä¿çã |
| | | |
| | | -- 1. å é¤éå®è´¨æ£æé®æé |
| | | UPDATE system_menu SET deleted = b'1', update_time = NOW() |
| | | WHERE deleted = b'0' |
| | | AND permission IN ('mes:qc-oqc:retest', 'mes:qc-oqc:sales-approve', 'mes:qc-oqc:company-approve'); |
| | | |
| | | -- 2. é»è¾å é¤âéå®è´¨æ£âèå |
| | | UPDATE system_menu SET deleted = b'1', update_time = NOW() |
| | | WHERE deleted = b'0' AND parent_id = 5500 AND path = 'sales-quality'; |
| | | |
| | | -- 3. æ¸
çè§è²ä¸éå®è´¨æ£èåçå
³èï¼system_role_menu æ deleted åï¼ç©çå é¤ï¼ |
| | | DELETE rm FROM system_role_menu rm |
| | | JOIN system_menu m ON rm.menu_id = m.id |
| | | WHERE m.permission IN ('mes:qc-oqc:retest', 'mes:qc-oqc:sales-approve', 'mes:qc-oqc:company-approve') |
| | | OR (m.parent_id = 5500 AND m.path = 'sales-quality'); |
| | | |
| | | -- 4. é»è¾å é¤éå®è´¨æ£å®¡æ ¸äººé
ç½® |
| | | UPDATE mes_qc_approver_config SET deleted = b'1', update_time = NOW() |
| | | WHERE deleted = b'0' AND qc_type = 2; |
| | | |
| | | -- å¯éï¼ç¡®è®¤æ å岿°æ®åï¼åæ¸
çéå®è´¨æ£éççè¡¨ç»æä¸å段 |
| | | -- DROP TABLE IF EXISTS mes_qc_oqc_action; |
| | | -- ALTER TABLE mes_qc_oqc |
| | | -- DROP COLUMN workflow_status, |
| | | -- DROP COLUMN inspection_round, |
| | | -- DROP COLUMN retest_of_id; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ç§åè´¨æ£åé¡¹åæ ¼èå´æ¨¡æ¿ã忣ä¸å¤æ£å¯ä¿®æ¹æ¬æ¬¡èå´ï¼æå®é
æäº¤å¼å¤å®ã |
| | | CREATE TABLE IF NOT EXISTS mes_qc_seed_indicator_range ( |
| | | indicator_code varchar(32) NOT NULL COMMENT 'purity/cleanliness/germination_rate/moisture', |
| | | min_value decimal(18,6) NOT NULL COMMENT 'åæ ¼ä¸éï¼å«è¾¹ç', |
| | | max_value decimal(18,6) NOT NULL COMMENT 'åæ ¼ä¸éï¼å«è¾¹ç', |
| | | creator varchar(64) DEFAULT '', |
| | | create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | updater varchar(64) DEFAULT '', |
| | | update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
| | | deleted bit(1) NOT NULL DEFAULT b'0', |
| | | PRIMARY KEY (indicator_code) |
| | | ) ENGINE=InnoDB COMMENT='ç§åè´¨æ£é¡¹åæ ¼èå´é
ç½®'; |
| | | |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'è´¨æ£é¡¹åæ ¼èå´é
ç½®', '', 2, 10, 5500, 'seed-range', 'ep:data-analysis', 'mes/qc/seedRange/index', 'MesQcSeedRange', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM system_menu WHERE parent_id = 5500 AND path = 'seed-range' AND deleted = b'0'); |
| | | |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'æ¥è¯¢', 'mes:qc-seed-range:query', 3, 1, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'seed-range' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-seed-range:query' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'ä¿®æ¹', 'mes:qc-seed-range:update', 3, 2, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'seed-range' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-seed-range:update' AND m.deleted = b'0'); |
| | |
| | | -- ç产质æ£ï¼åæ£ã夿£ãå å·¥é¨å®¡æ¹ãå
¬å¸è´¨æ£å®¡æ¹åææ¾è¡åºåã |
| | | -- ç产质æ£ï¼åæ£å®¡æ ¸ã夿£ã夿£å®¡æ ¸åææ¾è¡æå¤ç½®åºåã |
| | | -- å
é¨ç½²æ°æ®åºåæ´ï¼åé¨ç½²å¯¹åºå端ä¸å端ï¼åå²åæ ¼è®°å½å·²å®æåºåæµè½¬ã |
| | | ALTER TABLE mes_qc_seed_quality |
| | | ADD COLUMN workflow_status tinyint NOT NULL DEFAULT 40 COMMENT '10å¾
夿£ 20å¾
å å·¥é¨å®¡æ¹ 30å¾
å
¬å¸è´¨æ£å®¡æ¹ 40å·²æ¾è¡ 50å¾
å å·¥é¨ä¸åæ ¼è¯å®¡ 60å¾
å
¬å¸ä¸åæ ¼å®¡æ¹ 70å·²æ¥åº', |
| | | ADD COLUMN workflow_status tinyint NOT NULL DEFAULT 40 COMMENT '10å¾
夿£ 20å¾
åæ£å®¡æ ¸ 25å¾
忣ä¸åæ ¼å¤ç 30å¾
夿£å®¡æ ¸ 40å·²æ¾è¡ 50忣驳åå¾
鿣 60å¾
夿£ä¸åæ ¼å¤ç 70å·²æ¥åº', |
| | | ADD COLUMN qualified_warehouse_id bigint DEFAULT NULL COMMENT '审æ¹éè¿åçç®æ åæ ¼åº', |
| | | ADD COLUMN retest_result tinyint DEFAULT NULL COMMENT '夿£ç»æ 1åæ ¼ 2ä¸åæ ¼', |
| | | ADD COLUMN retested_at datetime DEFAULT NULL COMMENT '夿£æ¶é´', |
| | |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'seed-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-seed-quality:retest' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'å å·¥é¨å®¡æ¹', 'mes:qc-seed-quality:process-approve', 3, 4, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | SELECT 'åæ£å®¡æ ¸', 'mes:qc-seed-quality:process-approve', 3, 4, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'seed-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-seed-quality:process-approve' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'å
¬å¸è´¨æ£å®¡æ¹', 'mes:qc-seed-quality:company-approve', 3, 5, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | SELECT '夿£å®¡æ ¸', 'mes:qc-seed-quality:company-approve', 3, 5, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'seed-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-seed-quality:company-approve' AND m.deleted = b'0'); |
| | | |
| | | -- ç¬ç«éå®è´¨æ£å
¥å£ï¼ä¿çåâåºè´§æ£éªâèåï¼å¤ç¨å
¶å·²å®ç°çéå®åºåºåæ£éªè½åã |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'éå®è´¨æ£', '', 2, 8, 5500, 'sales-quality', 'ep:document-checked', 'mes/qc/salesQuality/index', 'MesQcSalesQuality', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM system_menu WHERE parent_id = 5500 AND path = 'sales-quality' AND deleted = b'0'); |
| | | |
| | | -- éå®è´¨æ£å¤æ£å两级审æ¹ï¼åå²å·²å®æåºè´§æ£éªåç»´ææ¢ææ¾è¡ç»æã |
| | | ALTER TABLE mes_qc_oqc |
| | | ADD COLUMN workflow_status tinyint NOT NULL DEFAULT 0 COMMENT '0è稿 10å¾
夿£ 20å¾
éå®é¨å®¡æ¹ 30å¾
å
¬å¸è´¨æ£å®¡æ¹ 40å·²æ¾è¡ 50å¾
éå®é¨ä¸åæ ¼è¯å®¡ 60å¾
å
¬å¸ä¸åæ ¼å®¡æ¹ 70å·²æç»åºè´§'; |
| | | CREATE INDEX idx_mes_oqc_workflow ON mes_qc_oqc (workflow_status, id); |
| | | UPDATE mes_qc_oqc SET workflow_status = CASE |
| | | WHEN status = 0 THEN 0 |
| | | WHEN check_result = 1 THEN 40 |
| | | ELSE 70 END; |
| | | CREATE TABLE IF NOT EXISTS mes_qc_oqc_action ( |
| | | id bigint NOT NULL AUTO_INCREMENT, |
| | | oqc_id bigint NOT NULL, |
| | | action varchar(32) NOT NULL, |
| | | result tinyint DEFAULT NULL, |
| | | opinion varchar(500) DEFAULT NULL, |
| | | quantities_json text DEFAULT NULL, |
| | | operator_id bigint DEFAULT NULL, |
| | | create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | PRIMARY KEY (id), |
| | | KEY idx_oqc_time (oqc_id, create_time) |
| | | ) ENGINE=InnoDB COMMENT='éå®è´¨æ£å¤æ£å审æ¹çç'; |
| | | |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'éå®å¤æ£', 'mes:qc-oqc:retest', 3, 1, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'sales-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-oqc:retest' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'éå®é¨å®¡æ¹', 'mes:qc-oqc:sales-approve', 3, 2, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'sales-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-oqc:sales-approve' AND m.deleted = b'0'); |
| | | INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) |
| | | SELECT 'éå®å
¬å¸è´¨æ£å®¡æ¹', 'mes:qc-oqc:company-approve', 3, 3, id, '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' |
| | | FROM system_menu WHERE parent_id = 5500 AND path = 'sales-quality' AND deleted = b'0' |
| | | AND NOT EXISTS (SELECT 1 FROM system_menu m WHERE m.parent_id = system_menu.id AND m.permission = 'mes:qc-oqc:company-approve' AND m.deleted = b'0'); |
| | |
| | | return success(new PageResult<>(buildBagCodeRespVOList(pageResult.getList()), pageResult.getTotal())); |
| | | } |
| | | |
| | | @GetMapping("/unbound-ton-bags") |
| | | @Operation(summary = "è·å¾å¯ç»å®çäº§æ¹æ¬¡çå¨è¢") |
| | | @PreAuthorize("@ss.hasAnyPermissions('mes:pro-batch:create', 'mes:pro-batch:update', 'mes:pro-bag-code:query')") |
| | | public CommonResult<List<MesProBagCodeRespVO>> getUnboundTonBags() { |
| | | return success(buildBagCodeRespVOList(bagCodeService.getUnboundTonBags())); |
| | | } |
| | | |
| | | @GetMapping("/list-by-uuid") |
| | | @Operation(summary = "è·å¾çæç»çè¢ç å表") |
| | | @Parameter(name = "uuid", description = "çæç» UUID", required = true) |
| | |
| | | return success(null); |
| | | } |
| | | MesProBatchRespVO respVO = buildBatchRespVOList(Collections.singletonList(batch)).get(0); |
| | | respVO.setBindingMode(batchService.getBindingMode(id)); |
| | | // å¡«å
人åé
ç½® |
| | | respVO.setWorkers(buildWorkerRespVOList(batchService.getBatchWorkerListByBatchId(id))); |
| | | return success(respVO); |
| | |
| | | private String tempCode; |
| | | @ExcelIgnore |
| | | private Long itemId; |
| | | @Schema(description = "å·²æç»å®æ¹å¼ï¼pallet æ tonBag") |
| | | @ExcelIgnore |
| | | private String bindingMode; |
| | | @ExcelProperty("åç§ç¼ç ") |
| | | private String itemCode; |
| | | @ExcelProperty("åç§åç§°") |
| | |
| | | |
| | | @Schema(description = "ç¼å·", example = "1024") |
| | | private Long id; |
| | | @Schema(description = "åç§ç¼å·ï¼ç±ç»å®æç带å
¥å¹¶ç»åç«¯æ ¡éª") |
| | | @Schema(description = "åç§ç¼å·ï¼ç±ç»å®æçæå¨è¢å¸¦å
¥å¹¶ç»åç«¯æ ¡éª") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "产线ç¼å·ï¼é¡µé¢å±ç¤ºä¸ºãå å·¥åä½ãï¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | |
| | | @Schema(description = "ç»å®æçç¼å·å表ï¼å¯éï¼ç»å®æ¶æ¹æ¬¡ç´æ¥è¿å
¥ç产ä¸ï¼æçä¸è¢ç 级èå½å
¥æ¬æ¹æ¬¡ï¼æ°å¢/è¡¥å½/ç¼è¾åå¯ä¼ å
¥ï¼ç¼è¾æ¶ä»
éä¼ æ¬æ¬¡æ°å¢å¾éçæçï¼") |
| | | private List<Long> palletIds; |
| | | |
| | | @Schema(description = "ç»å®å¨è¢ç¼å·å表ï¼ä»
计éåä½ä¸ºå¨ä¸æ æççè¢ç ï¼ä¸ç»å®æçäºæ¥ï¼") |
| | | private List<Long> tonBagIds; |
| | | |
| | | @Schema(description = "ç产人åé
ç½®") |
| | | @Data |
| | | public static class Worker { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.approver; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.approver.MesQcApproverConfigDO; |
| | | import cn.iocoder.yudao.module.mes.service.qc.approver.MesQcApproverService; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; |
| | | |
| | | @Tag(name = "管çåå° - MES è´¨æ£å®¡æ ¸äººé
ç½®") |
| | | @RestController |
| | | @RequestMapping("/mes/qc/approver-config") |
| | | @Validated |
| | | public class MesQcApproverConfigController { |
| | | |
| | | @Resource |
| | | private MesQcApproverService approverService; |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建质æ£å®¡æ ¸äººé
ç½®") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-approver:create')") |
| | | public CommonResult<Long> createConfig(@Valid @RequestBody MesQcApproverConfigSaveReqVO reqVO) { |
| | | return success(approverService.createConfig(reqVO)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "æ´æ°è´¨æ£å®¡æ ¸äººé
ç½®") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-approver:update')") |
| | | public CommonResult<Boolean> updateConfig(@Valid @RequestBody MesQcApproverConfigSaveReqVO reqVO) { |
| | | approverService.updateConfig(reqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "å é¤è´¨æ£å®¡æ ¸äººé
ç½®") |
| | | @Parameter(name = "id", description = "ç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-approver:delete')") |
| | | public CommonResult<Boolean> deleteConfig(@RequestParam("id") Long id) { |
| | | approverService.deleteConfig(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å¾è´¨æ£å®¡æ ¸äººé
ç½®") |
| | | @Parameter(name = "id", description = "ç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-approver:query')") |
| | | public CommonResult<MesQcApproverConfigRespVO> getConfig(@RequestParam("id") Long id) { |
| | | MesQcApproverConfigDO config = approverService.getConfig(id); |
| | | return success(buildRespVOList(List.of(config)).get(0)); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "è·å¾è´¨æ£å®¡æ ¸äººé
ç½®å页") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-approver:query')") |
| | | public CommonResult<PageResult<MesQcApproverConfigRespVO>> getConfigPage(@Valid MesQcApproverConfigPageReqVO pageReqVO) { |
| | | PageResult<MesQcApproverConfigDO> pageResult = approverService.getConfigPage(pageReqVO); |
| | | return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); |
| | | } |
| | | |
| | | private List<MesQcApproverConfigRespVO> buildRespVOList(List<MesQcApproverConfigDO> list) { |
| | | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( |
| | | convertSet(list, MesQcApproverConfigDO::getUserId)); |
| | | return BeanUtils.toBean(list, MesQcApproverConfigRespVO.class, vo -> |
| | | findAndThen(userMap, vo.getUserId(), user -> vo.setUserNickname(user.getNickname()))); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | @Schema(description = "管çåå° - è´¨æ£å®¡æ ¸äººé
ç½®å页 Request VO") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class MesQcApproverConfigPageReqVO extends PageParam { |
| | | |
| | | @Schema(description = "è´¨æ£ç±»åï¼1ç§åè´¨æ£", example = "1") |
| | | private Integer qcType; |
| | | |
| | | @Schema(description = "å®¡æ ¸èç¹ï¼1å å·¥é¨å®¡æ¹ 3å
¬å¸è´¨æ£å®¡æ¹", example = "3") |
| | | private Integer approveNode; |
| | | |
| | | @Schema(description = "å®¡æ ¸äººç¨æ· ID", example = "1024") |
| | | private Long userId; |
| | | |
| | | @Schema(description = "ç¶æï¼0å¯ç¨ 1åç¨", example = "0") |
| | | private Integer status; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "管çåå° - è´¨æ£å®¡æ ¸äººé
ç½® Response VO") |
| | | @Data |
| | | public class MesQcApproverConfigRespVO { |
| | | |
| | | @Schema(description = "ç¼å·", example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "è´¨æ£ç±»åï¼1ç§åè´¨æ£", example = "1") |
| | | private Integer qcType; |
| | | |
| | | @Schema(description = "å®¡æ ¸èç¹ï¼1å å·¥é¨å®¡æ¹ 3å
¬å¸è´¨æ£å®¡æ¹", example = "3") |
| | | private Integer approveNode; |
| | | |
| | | @Schema(description = "å®¡æ ¸äººç¨æ· ID", example = "1024") |
| | | private Long userId; |
| | | |
| | | @Schema(description = "å®¡æ ¸äººæµç§°", example = "å¼ ä¸") |
| | | private String userNickname; |
| | | |
| | | @Schema(description = "ç¶æï¼0å¯ç¨ 1åç¨", example = "0") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "夿³¨", example = "è´è´£ç§åè´¨æ£å
¬å¸å®¡æ¹") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | @Schema(description = "管çåå° - è´¨æ£å®¡æ ¸äººé
ç½®æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | | public class MesQcApproverConfigSaveReqVO { |
| | | |
| | | @Schema(description = "ç¼å·", example = "1024") |
| | | private Long id; |
| | | |
| | | @Schema(description = "è´¨æ£ç±»åï¼1ç§åè´¨æ£", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "è´¨æ£ç±»åä¸è½ä¸ºç©º") |
| | | private Integer qcType; |
| | | |
| | | @Schema(description = "å®¡æ ¸èç¹ï¼1å å·¥é¨å®¡æ¹ 3å
¬å¸è´¨æ£å®¡æ¹", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") |
| | | @NotNull(message = "å®¡æ ¸èç¹ä¸è½ä¸ºç©º") |
| | | private Integer approveNode; |
| | | |
| | | @Schema(description = "å®¡æ ¸äººç¨æ· ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "å®¡æ ¸äººä¸è½ä¸ºç©º") |
| | | private Long userId; |
| | | |
| | | @Schema(description = "ç¶æï¼0å¯ç¨ 1åç¨", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | @NotNull(message = "ç¶æä¸è½ä¸ºç©º") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "夿³¨", example = "è´è´£ç§åè´¨æ£å
¬å¸å®¡æ¹") |
| | | private String remark; |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcApprovalReqVO; |
| | | 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.dal.dataobject.md.item.MesMdItemDO; |
| | |
| | | public CommonResult<Boolean> finishOqc(@RequestParam("id") Long id) { |
| | | oqcService.finishOqc(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/retest") @Operation(summary = "éå®è´¨æ£å¤æ£") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-oqc:retest')") |
| | | public CommonResult<Boolean> retestOqc(@Valid @RequestBody MesQcOqcRetestReqVO reqVO) { |
| | | oqcService.retestOqc(reqVO); |
| | | return success(true); |
| | | } |
| | | @PostMapping("/sales-approve") @Operation(summary = "éå®é¨å®¡æ¹") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-oqc:sales-approve')") |
| | | public CommonResult<Boolean> salesApprove(@Valid @RequestBody MesQcOqcApprovalReqVO reqVO) { |
| | | oqcService.salesApprove(reqVO.getId(), reqVO.getApproved(), reqVO.getOpinion()); |
| | | return success(true); |
| | | } |
| | | @PostMapping("/company-approve") @Operation(summary = "å
¬å¸è´¨æ£å®¡æ¹éå®åºè´§") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-oqc:company-approve')") |
| | | public CommonResult<Boolean> companyApprove(@Valid @RequestBody MesQcOqcApprovalReqVO reqVO) { |
| | | oqcService.companyApprove(reqVO.getId(), reqVO.getApproved(), reqVO.getOpinion()); |
| | | return success(true); |
| | | } |
| | | @GetMapping("/actions") @Operation(summary = "éå®è´¨æ£æµç¨è®°å½") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-oqc:query')") |
| | | public CommonResult<List<cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcActionDO>> actions(@RequestParam Long id) { |
| | | return success(oqcService.getActions(id)); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | |
| | | |
| | | @Schema(description = "æ£æµç»æ", example = "1") |
| | | private Integer checkResult; |
| | | @Schema(description = "æ¥æºåæ®ç±»å") |
| | | private Integer sourceDocType; |
| | | |
| | | } |
| | |
| | | @Schema(description = "ç¶æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | @ExcelProperty("ç¶æ") |
| | | private Integer status; |
| | | private Integer workflowStatus; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | @ExcelProperty("夿³¨") |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityApprovalReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityBatchApprovalReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityBatchRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityScopeRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedIndicatorRangeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper; |
| | | import cn.iocoder.yudao.module.mes.service.qc.seedquality.MesQcSeedQualityService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.seedquality.MesQcSeedIndicatorRangeService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | |
| | | @Tag(name = "管çåå° - MES ç§åè´¨æ£") |
| | | @RestController @RequestMapping("/mes/qc/seed-quality") @Validated |
| | | public class MesQcSeedQualityController { |
| | | @Resource private MesQcSeedQualityService service; |
| | | @Resource private MesQcSeedIndicatorRangeService rangeService; |
| | | @Resource private MesProBagCodeMapper bagCodeMapper; |
| | | @GetMapping("/ranges") @Operation(summary = "è·å¾ç§åè´¨æ£åæ ¼èå´") |
| | | @PreAuthorize("@ss.hasAnyPermissions('mes:qc-seed-quality:submit', 'mes:qc-seed-quality:retest', 'mes:qc-seed-range:query')") |
| | | public CommonResult<java.util.List<cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedIndicatorRangeDO>> ranges() { |
| | | return success(rangeService.getRanges()); |
| | | } |
| | | |
| | | @PutMapping("/ranges") @Operation(summary = "é
ç½®ç§åè´¨æ£åæ ¼èå´") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-range:update')") |
| | | public CommonResult<Boolean> saveRanges(@Valid @RequestBody MesQcSeedIndicatorRangeSaveReqVO reqVO) { |
| | | rangeService.saveRanges(reqVO); |
| | | return success(true); |
| | | } |
| | | @GetMapping("/resolve") |
| | | @Operation(summary = "è§£æå¾
è´¨æ£è¢ç å确认该è¢è´¨æ£ç»æ") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:submit')") |
| | |
| | | @Operation(summary = "è·å¾ç§åè´¨æ£è®°å½å页") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:query')") |
| | | public CommonResult<PageResult<MesQcSeedQualityRespVO>> getQualityPage(@Valid MesQcSeedQualityPageReqVO pageReqVO) { |
| | | return success(BeanUtils.toBean(service.getQualityPage(pageReqVO), MesQcSeedQualityRespVO.class)); |
| | | PageResult<MesQcSeedQualityRespVO> page = BeanUtils.toBean( |
| | | service.getQualityPage(pageReqVO), MesQcSeedQualityRespVO.class); |
| | | List<String> codes = page.getList().stream().map(MesQcSeedQualityRespVO::getCode) |
| | | .filter(java.util.Objects::nonNull).distinct().toList(); |
| | | if (!codes.isEmpty()) { |
| | | Map<String, MesProBagCodeDO> bagMap = bagCodeMapper.selectList(MesProBagCodeDO::getCode, codes).stream() |
| | | .collect(Collectors.toMap(MesProBagCodeDO::getCode, Function.identity(), (first, ignored) -> first)); |
| | | page.getList().forEach(record -> { |
| | | MesProBagCodeDO bag = bagMap.get(record.getCode()); |
| | | if (bag != null) record.setPalletCode(bag.getPalletCode()); |
| | | }); |
| | | } |
| | | return success(page); |
| | | } |
| | | |
| | | @GetMapping("/indicators") @Operation(summary = "è·å¾ç§åè´¨æ£ææ°ææ ") |
| | |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/process-approve") @Operation(summary = "å å·¥é¨å®¡æ¹") |
| | | @PostMapping("/retest-batch") @Operation(summary = "åæ¹æ¬¡ç§åæ¹é夿£æéæ°åæ£") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:retest')") |
| | | public CommonResult<Boolean> retestBatch(@Valid @RequestBody MesQcSeedQualityBatchRetestReqVO reqVO) { |
| | | service.retestBatch(reqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/retest-scope/resolve") @Operation(summary = "ææçç æçäº§æ¹æ¬¡ç è§£æå¾
æ¹éè´¨æ£è®°å½") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:retest')") |
| | | public CommonResult<java.util.Map<String, Object>> resolveRetestScope(@RequestParam String code, @RequestParam String scanType) { |
| | | return success(service.resolveRetestScope(code, scanType)); |
| | | } |
| | | |
| | | @PostMapping("/retest-scope") @Operation(summary = "ææçç æçäº§æ¹æ¬¡ç æ¹é夿£æéæ°åæ£") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:retest')") |
| | | public CommonResult<java.util.Map<String, Object>> retestScope(@Valid @RequestBody MesQcSeedQualityScopeRetestReqVO reqVO) { |
| | | return success(service.retestScope(reqVO)); |
| | | } |
| | | |
| | | @PostMapping("/process-approve") @Operation(summary = "åæ£å®¡æ ¸") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:process-approve')") |
| | | public CommonResult<Boolean> processApprove(@Valid @RequestBody MesQcSeedQualityApprovalReqVO reqVO) { |
| | | service.processApprove(reqVO.getId(), reqVO.getApproved(), reqVO.getOpinion()); |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/company-approve") @Operation(summary = "å
¬å¸è´¨æ£å®¡æ¹å¹¶æµè½¬åºå") |
| | | @PostMapping("/company-approve") @Operation(summary = "夿£å®¡æ ¸å¹¶æµè½¬åºå") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:company-approve')") |
| | | public CommonResult<Boolean> companyApprove(@Valid @RequestBody MesQcSeedQualityApprovalReqVO reqVO) { |
| | | service.companyApprove(reqVO.getId(), reqVO.getApproved(), reqVO.getOpinion()); |
| | | return success(true); |
| | | } |
| | | @PostMapping("/process-approve-batch") @Operation(summary = "æ¹éå å·¥é¨å®¡æ¹") |
| | | @PostMapping("/process-approve-batch") @Operation(summary = "æ¹éåæ£å®¡æ ¸") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:process-approve')") |
| | | public CommonResult<Boolean> processApproveBatch(@Valid @RequestBody MesQcSeedQualityBatchApprovalReqVO reqVO) { |
| | | service.processApproveBatch(reqVO.getIds(), reqVO.getApproved(), reqVO.getOpinion()); |
| | | return success(true); |
| | | } |
| | | @PostMapping("/company-approve-batch") @Operation(summary = "æ¹éå
¬å¸è´¨æ£å®¡æ¹å¹¶æµè½¬åºå") |
| | | @PostMapping("/company-approve-batch") @Operation(summary = "æ¹é夿£å®¡æ ¸å¹¶æµè½¬åºå") |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-seed-quality:company-approve')") |
| | | public CommonResult<Boolean> companyApproveBatch(@Valid @RequestBody MesQcSeedQualityBatchApprovalReqVO reqVO) { |
| | | service.companyApproveBatch(reqVO.getIds(), reqVO.getApproved(), reqVO.getOpinion()); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo; |
| | | |
| | | import jakarta.validation.Valid; |
| | | import jakarta.validation.constraints.DecimalMax; |
| | | import jakarta.validation.constraints.DecimalMin; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class MesQcSeedIndicatorRangeSaveReqVO { |
| | | @NotEmpty |
| | | private List<@Valid Item> ranges; |
| | | |
| | | @Data |
| | | public static class Item { |
| | | @NotBlank private String indicatorCode; |
| | | @NotNull @DecimalMin("0") @DecimalMax("100") private BigDecimal minValue; |
| | | @NotNull @DecimalMin("0") @DecimalMax("100") private BigDecimal maxValue; |
| | | } |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | |
| | | public class MesQcSeedQualityApprovalReqVO { |
| | | @NotNull private Long id; |
| | | @NotNull private Boolean approved; |
| | | @NotBlank private String opinion; |
| | | private String opinion; |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | |
| | | public class MesQcSeedQualityBatchApprovalReqVO { |
| | | @NotEmpty private List<@NotNull Long> ids; |
| | | @NotNull private Boolean approved; |
| | | @NotBlank private String opinion; |
| | | private String opinion; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo; |
| | | |
| | | import jakarta.validation.Valid; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class MesQcSeedQualityBatchRetestReqVO { |
| | | @NotEmpty private List<@NotNull Long> ids; |
| | | @NotEmpty @Valid private List<MesQcSeedQualitySubmitReqVO.Indicator> indicators; |
| | | private String reason; |
| | | } |
| | |
| | | |
| | | private Long id; |
| | | private String code; |
| | | @Schema(description = "å¯¹åºæçç ï¼æªç»å®æçæ¶ä¸ºç©º") |
| | | private String palletCode; |
| | | private Long itemId; |
| | | private Long batchId; |
| | | private String batchCode; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo; |
| | | |
| | | import jakarta.validation.Valid; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class MesQcSeedQualityScopeRetestReqVO { |
| | | @NotBlank private String code; |
| | | @NotBlank private String scanType; |
| | | @NotNull private Integer workflowStatus; |
| | | @NotEmpty private List<@NotNull Long> qualityIds; |
| | | @NotEmpty @Valid private List<MesQcSeedQualitySubmitReqVO.Indicator> indicators; |
| | | private String reason; |
| | | } |
| | |
| | | @NotNull private Long qualifiedWarehouseId; |
| | | @Data public static class Indicator { |
| | | @NotBlank private String code; |
| | | @NotNull @DecimalMin("0") private BigDecimal value; |
| | | @NotNull @DecimalMin("0") private BigDecimal minValue; |
| | | @NotNull @DecimalMin("0") private BigDecimal maxValue; |
| | | @NotNull @DecimalMin("0") @DecimalMax("100") private BigDecimal value; |
| | | @NotNull @DecimalMin("0") @DecimalMax("100") private BigDecimal minValue; |
| | | @NotNull @DecimalMin("0") @DecimalMax("100") private BigDecimal maxValue; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.dataobject.qc.approver; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcApproveNodeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcApprovalTypeEnum; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸äººé
ç½® DO |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @TableName("mes_qc_approver_config") |
| | | @KeySequence("mes_qc_approver_config_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class MesQcApproverConfigDO extends BaseDO { |
| | | |
| | | /** |
| | | * ç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * è´¨æ£ç±»å |
| | | * |
| | | * æä¸¾ {@link MesQcApprovalTypeEnum} |
| | | */ |
| | | private Integer qcType; |
| | | /** |
| | | * å®¡æ ¸èç¹ |
| | | * |
| | | * æä¸¾ {@link MesQcApproveNodeEnum} |
| | | */ |
| | | private Integer approveNode; |
| | | /** |
| | | * å®¡æ ¸äººç¨æ· ID |
| | | */ |
| | | private Long userId; |
| | | /** |
| | | * ç¶æï¼0 å¯ç¨ï¼1 åç¨ |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| | |
| | | * æä¸¾ {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum} |
| | | */ |
| | | private Integer status; |
| | | /** 0è稿ï¼10å¾
夿£ï¼20å¾
éå®é¨å®¡æ¹ï¼30å¾
å
¬å¸è´¨æ£å®¡æ¹ï¼40å·²æ¾è¡ï¼50å¾
éå®é¨ä¸åæ ¼è¯å®¡ï¼60å¾
å
¬å¸ä¸åæ ¼å®¡æ¹ï¼70å·²æç»åºè´§ã */ |
| | | private Integer workflowStatus; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @TableName("mes_qc_seed_indicator_range") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class MesQcSeedIndicatorRangeDO extends BaseDO { |
| | | @TableId(type = IdType.INPUT) |
| | | private String indicatorCode; |
| | | private BigDecimal minValue; |
| | | private BigDecimal maxValue; |
| | | } |
| | |
| | | private String batchCode; |
| | | private Integer result; |
| | | private String reason; |
| | | /** 10 å¾
夿£ï¼20 å¾
å å·¥é¨å®¡æ¹ï¼30 å¾
å
¬å¸è´¨æ£å®¡æ¹ï¼40 å·²æ¾è¡ï¼50 å¾
å å·¥é¨ä¸åæ ¼è¯å®¡ï¼60 å¾
å
¬å¸ä¸åæ ¼å®¡æ¹ï¼70 å·²æ¥åºã */ |
| | | /** 10 å¾
夿£ï¼20 å¾
åæ£å®¡æ ¸ï¼25 å¾
忣ä¸åæ ¼å¤çï¼30 å¾
夿£å®¡æ ¸ï¼40 å·²æ¾è¡ï¼50 忣驳åå¾
鿣ï¼60 å¾
夿£ä¸åæ ¼å¤çï¼70 å·²æ¥åºã */ |
| | | private Integer workflowStatus; |
| | | private Long qualifiedWarehouseId; |
| | | private Integer retestResult; |
| | |
| | | return selectOne(MesMdItemDO::getCode, code); |
| | | } |
| | | |
| | | default MesMdItemDO selectByName(String name) { |
| | | return selectOne(MesMdItemDO::getName, name); |
| | | } |
| | | |
| | | default Long selectCountByItemTypeId(Long itemTypeId) { |
| | | return selectCount(MesMdItemDO::getItemTypeId, itemTypeId); |
| | | } |
| | |
| | | .orderByAsc(MesProBagCodeDO::getId)); |
| | | } |
| | | |
| | | default List<MesProBagCodeDO> selectUnboundPalletlessList() { |
| | | return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>() |
| | | .isNull(MesProBagCodeDO::getBatchId) |
| | | .isNull(MesProBagCodeDO::getPalletId) |
| | | .in(MesProBagCodeDO::getStatus, MesProBagCodeStatusEnum.GENERATED.getStatus(), |
| | | MesProBagCodeStatusEnum.PRINTED.getStatus()) |
| | | .isNotNull(MesProBagCodeDO::getItemId) |
| | | .orderByAsc(MesProBagCodeDO::getId)); |
| | | } |
| | | |
| | | /** æ¹æ¬¡å
ææè¢ç çåç§ç¼å·éåï¼å¿½ç¥åå²ç©ºåç§è¢ç ï¼ï¼ç¨äºå½å
¥æ¹æ¬¡æ¶çåç§ä¸è´æ§æ ¡éª */ |
| | | @Select("SELECT DISTINCT item_id FROM mes_pro_bag_code " + |
| | | "WHERE deleted = 0 AND status <> 30 AND batch_id = #{batchId} AND item_id IS NOT NULL") |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.mysql.qc.approver; |
| | | |
| | | 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.qc.approver.vo.MesQcApproverConfigPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.approver.MesQcApproverConfigDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸äººé
ç½® Mapper |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Mapper |
| | | public interface MesQcApproverConfigMapper extends BaseMapperX<MesQcApproverConfigDO> { |
| | | |
| | | default PageResult<MesQcApproverConfigDO> selectPage(MesQcApproverConfigPageReqVO reqVO) { |
| | | return selectPage(reqVO, new LambdaQueryWrapperX<MesQcApproverConfigDO>() |
| | | .eqIfPresent(MesQcApproverConfigDO::getQcType, reqVO.getQcType()) |
| | | .eqIfPresent(MesQcApproverConfigDO::getApproveNode, reqVO.getApproveNode()) |
| | | .eqIfPresent(MesQcApproverConfigDO::getUserId, reqVO.getUserId()) |
| | | .eqIfPresent(MesQcApproverConfigDO::getStatus, reqVO.getStatus()) |
| | | .orderByAsc(MesQcApproverConfigDO::getQcType) |
| | | .orderByAsc(MesQcApproverConfigDO::getApproveNode) |
| | | .orderByDesc(MesQcApproverConfigDO::getId)); |
| | | } |
| | | |
| | | default MesQcApproverConfigDO selectByUnique(Integer qcType, Integer approveNode, Long userId) { |
| | | return selectOne(new LambdaQueryWrapperX<MesQcApproverConfigDO>() |
| | | .eq(MesQcApproverConfigDO::getQcType, qcType) |
| | | .eq(MesQcApproverConfigDO::getApproveNode, approveNode) |
| | | .eq(MesQcApproverConfigDO::getUserId, userId)); |
| | | } |
| | | |
| | | default Long selectCountByNode(Integer qcType, Integer approveNode, Integer status) { |
| | | return selectCount(new LambdaQueryWrapperX<MesQcApproverConfigDO>() |
| | | .eq(MesQcApproverConfigDO::getQcType, qcType) |
| | | .eq(MesQcApproverConfigDO::getApproveNode, approveNode) |
| | | .eq(MesQcApproverConfigDO::getStatus, status)); |
| | | } |
| | | |
| | | } |
| | |
| | | .likeIfPresent(MesQcOqcDO::getBatchCode, reqVO.getBatchCode()) |
| | | .eqIfPresent(MesQcOqcDO::getItemId, reqVO.getItemId()) |
| | | .eqIfPresent(MesQcOqcDO::getCheckResult, reqVO.getCheckResult()) |
| | | .eqIfPresent(MesQcOqcDO::getSourceDocType, reqVO.getSourceDocType()) |
| | | .orderByDesc(MesQcOqcDO::getId)); |
| | | } |
| | | |
| | |
| | | .likeIfPresent(MesQcOqcDO::getBatchCode, reqVO.getBatchCode()) |
| | | .eqIfPresent(MesQcOqcDO::getItemId, reqVO.getItemId()) |
| | | .eqIfPresent(MesQcOqcDO::getCheckResult, reqVO.getCheckResult()) |
| | | .eqIfPresent(MesQcOqcDO::getSourceDocType, reqVO.getSourceDocType()) |
| | | .orderByDesc(MesQcOqcDO::getId); |
| | | if (permittedClientIds != null) { |
| | | if (CollUtil.isEmpty(permittedClientIds)) { |
| | |
| | | |
| | | default MesQcOqcDO selectByCode(String code) { |
| | | return selectOne(MesQcOqcDO::getCode, code); |
| | | } |
| | | default MesQcOqcDO selectByIdForUpdate(Long id) { |
| | | return selectOne(new LambdaQueryWrapperX<MesQcOqcDO>().eq(MesQcOqcDO::getId, id).last("FOR UPDATE")); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedIndicatorRangeDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | @Mapper |
| | | public interface MesQcSeedIndicatorRangeMapper extends BaseMapperX<MesQcSeedIndicatorRangeDO> { |
| | | } |
| | |
| | | // ========== MES åºç¡æ°æ®-ç©æï¼1-040-102-000ï¼ ========== |
| | | ErrorCode MD_ITEM_NOT_EXISTS = new ErrorCode(1_040_102_000, "ç©æä¸åå¨"); |
| | | ErrorCode MD_ITEM_CODE_DUPLICATE = new ErrorCode(1_040_102_001, "ç©æç¼ç å·²åå¨"); |
| | | ErrorCode MD_ITEM_NAME_DUPLICATE = new ErrorCode(1_040_102_002, "ç©æåç§°å·²åå¨"); |
| | | ErrorCode MD_ITEM_BATCH_REQUIRED = new ErrorCode(1_040_102_004, "å½åç©æå¯ç¨äºæ¹æ¬¡ç®¡çï¼è¯·éæ©æ¹æ¬¡"); |
| | | ErrorCode MD_ITEM_IS_DISABLE = new ErrorCode(1_040_102_005, "ç©æå·²ç¦ç¨"); |
| | | |
| | |
| | | ErrorCode QC_NCR_NOT_REVIEWED = new ErrorCode(1_040_609_003, "åªæå·²è¯å®¡ç¶æçä¸åæ ¼åå¤çåæå¯æ§è¡å¤ç½®"); |
| | | ErrorCode QC_NCR_NOT_DISPOSED = new ErrorCode(1_040_609_004, "åªæå·²å¤ç½®ç¶æçä¸åæ ¼åå¤çåæå¯å
³é"); |
| | | |
| | | // ========== MES è´¨é管ç-è´¨æ£å®¡æ ¸äººé
ç½®ï¼1-040-610-000ï¼ ========== |
| | | ErrorCode QC_APPROVER_CONFIG_NOT_EXISTS = new ErrorCode(1_040_610_000, "è´¨æ£å®¡æ ¸äººé
ç½®ä¸åå¨"); |
| | | ErrorCode QC_APPROVER_CONFIG_DUPLICATE = new ErrorCode(1_040_610_001, "该质æ£ç±»ååå®¡æ ¸èç¹ä¸å·²åå¨è¯¥å®¡æ ¸äºº"); |
| | | ErrorCode QC_APPROVER_NODE_INVALID = new ErrorCode(1_040_610_002, "è´¨æ£ç±»åä¸å®¡æ ¸èç¹ç»åä¸åæ³"); |
| | | ErrorCode QC_APPROVER_NOT_CONFIGURED = new ErrorCode(1_040_610_003, "å½åç¨æ·ä¸æ¯è¯¥èç¹çè´¨æ£å®¡æ ¸äººï¼è¯·è系管çåé
ç½®"); |
| | | |
| | | // ========== MES ä»åºç®¡ç-ä»åºï¼1-040-700-000ï¼ ========== |
| | | ErrorCode WM_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_700_000, "ä»åºä¸åå¨"); |
| | | ErrorCode WM_WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_040_700_001, "ä»åºç¼ç å·²åå¨"); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.enums.qc; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸ç±»åæä¸¾ï¼ç¨äºå®¡æ ¸äººé
ç½®ï¼ |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum MesQcApprovalTypeEnum implements ArrayValuable<Integer> { |
| | | |
| | | SEED_QUALITY(1, "ç§åè´¨æ£"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcApprovalTypeEnum::getType).toArray(Integer[]::new); |
| | | |
| | | /** |
| | | * ç±»åå¼ |
| | | */ |
| | | private final Integer type; |
| | | /** |
| | | * ç±»åå |
| | | */ |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.enums.qc; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸èç¹æä¸¾ï¼ç¨äºå®¡æ ¸äººé
ç½®ï¼ |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum MesQcApproveNodeEnum implements ArrayValuable<Integer> { |
| | | |
| | | PROCESS(1, "åæ£å®¡æ ¸"), |
| | | COMPANY(3, "夿£å®¡æ ¸"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcApproveNodeEnum::getNode).toArray(Integer[]::new); |
| | | |
| | | /** |
| | | * èç¹å¼ |
| | | */ |
| | | private final Integer node; |
| | | /** |
| | | * èç¹å |
| | | */ |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªè´¨æ£ç±»åä¸å®¡æ ¸èç¹çç»åæ¯å¦åæ³ |
| | | */ |
| | | public static boolean isValidCombination(Integer qcType, Integer node) { |
| | | return Objects.equals(qcType, MesQcApprovalTypeEnum.SEED_QUALITY.getType()) |
| | | && Set.of(PROCESS.getNode(), COMPANY.getNode()).contains(node); |
| | | } |
| | | |
| | | } |
| | |
| | | private void validateItemSaveData(MesMdItemSaveReqVO reqVO) { |
| | | // æ ¡éªç©æç¼ç çå¯ä¸æ§ |
| | | validateItemCodeUnique(reqVO.getId(), reqVO.getCode()); |
| | | // æ ¡éªç©æåç§°çå¯ä¸æ§ |
| | | validateItemNameUnique(reqVO.getId(), reqVO.getName()); |
| | | // æ ¡éªç©æåç±»åå¨ï¼MDM åç§åæ¥ä¸ä¼ åç±»ï¼å
è®¸ä¸ºç©ºï¼ |
| | | if (reqVO.getItemTypeId() != null) { |
| | | validateItemTypeExists(reqVO.getItemTypeId()); |
| | |
| | | } |
| | | if (ObjUtil.notEqual(item.getId(), id)) { |
| | | throw exception(MD_ITEM_CODE_DUPLICATE); |
| | | } |
| | | } |
| | | |
| | | private void validateItemNameUnique(Long id, String name) { |
| | | MesMdItemDO item = itemMapper.selectByName(name); |
| | | if (item == null) { |
| | | return; |
| | | } |
| | | if (ObjUtil.notEqual(item.getId(), id)) { |
| | | throw exception(MD_ITEM_NAME_DUPLICATE); |
| | | } |
| | | } |
| | | |
| | |
| | | return item; |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | |
| | | void bindBatch(@Valid MesProBagCodeBindBatchReqVO bindReqVO); |
| | | |
| | | /** å°æªç»å®æ¹æ¬¡ã没ææçä¸åç§è®¡éåä½ä¸ºå¨çè¢ç ã */ |
| | | List<MesProBagCodeDO> getUnboundTonBags(); |
| | | |
| | | /** |
| | | * ä½åºç ´æè¢ç å¹¶å¨åæ¹æ¬¡çæçéæ¿æ¢è¢ç |
| | | */ |
| | |
| | | return type; |
| | | } |
| | | |
| | | @Override |
| | | public List<MesProBagCodeDO> getUnboundTonBags() { |
| | | Map<Long, Boolean> tonItems = new LinkedHashMap<>(); |
| | | return bagCodeMapper.selectUnboundPalletlessList().stream() |
| | | .filter(bag -> tonItems.computeIfAbsent(bag.getItemId(), id -> { |
| | | MesMdmItemDO item = mdmItemService.getItem(id); |
| | | if (item == null || item.getUnitMeasureId() == null) return false; |
| | | CommonResult<MdmUnitMeasureRespDTO> result = unitMeasureApi.getUnitMeasure(item.getUnitMeasureId()); |
| | | return result != null && result.isSuccess() && result.getData() != null |
| | | && UNIT_TYPE_TON.equals(StrUtil.trim(result.getData().getType())); |
| | | })) |
| | | .toList(); |
| | | } |
| | | |
| | | /** |
| | | * è§£æãNè¢ãç±»åå¾åºæ¯æçè¢æ° |
| | | */ |
| | |
| | | */ |
| | | MesProBatchDO getBatch(Long id); |
| | | |
| | | /** æ¹æ¬¡å·²æçç»å®æ¹å¼ï¼palletãtonBag æç©ºã */ |
| | | String getBindingMode(Long id); |
| | | |
| | | /** |
| | | * æ ¡éªçäº§æ¹æ¬¡åå¨ |
| | | * |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPreGenerateReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindBatchReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; |
| | | import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.pallet.vo.MesProPalletBindBatchReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchWorkerDO; |
| | |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.line.MesProLineService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService; |
| | | import cn.iocoder.yudao.module.mes.service.trace.integrity.MesTraceIntegrityService; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | |
| | | |
| | | @Resource |
| | | private MesProPalletService palletService; |
| | | @Resource |
| | | private MesProBagCodeService bagCodeService; |
| | | @Resource |
| | | private MesMdmItemService mdmItemService; |
| | | @Resource |
| | | private MdmUnitMeasureApi unitMeasureApi; |
| | | |
| | | @Resource |
| | | private MesCodeRedisDAO codeRedisDao; |
| | |
| | | String code = generateBatchCode(line.getCode()); |
| | | |
| | | // 3. æå
¥æ¹æ¬¡ï¼äº§çº¿ç¼ç /åç§°åä½åå¡«ï¼å¾éç»å®æçæ¶æ¹æ¬¡ç´æ¥è¿å
¥ç产ä¸ï¼ |
| | | boolean bindPallets = CollUtil.isNotEmpty(createReqVO.getPalletIds()); |
| | | boolean hasBindings = hasBindings(createReqVO); |
| | | MesProBatchDO batch = BeanUtils.toBean(createReqVO, MesProBatchDO.class) |
| | | .setCode(code) |
| | | .setBusinessCode(codeRedisDao.generate()) |
| | |
| | | .setLineName(line.getName()) |
| | | .setBagQuantity(0) |
| | | .setPalletQuantity(0) |
| | | .setStatus(bindPallets ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | .setStatus(hasBindings ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | : MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | batchMapper.insert(batch); |
| | | |
| | |
| | | insertBatchWorkers(batch.getId(), createReqVO.getWorkers()); |
| | | // 5. ç»å®æçï¼çº§èçææ£å¼æçç å¹¶å½å
¥æçä¸è¢ç ï¼å¤±è´¥æ´ä½åæ»ï¼ |
| | | bindPalletsToBatch(batch.getId(), createReqVO.getPalletIds()); |
| | | bindTonBagsToBatch(batch.getId(), createReqVO.getTonBagIds()); |
| | | // 6. çææ¹æ¬¡å®æ´æ§æè¦ |
| | | integrityService.recordBatchIntegrity(batch.getId()); |
| | | return batch.getId(); |
| | |
| | | fillReqVO.setItemId(resolveBindingItem(batch, fillReqVO)); |
| | | String code = generateBatchCode(line.getCode()); |
| | | // 3. è½åºä¸å¡ä¿¡æ¯ï¼ä¿çä¸´æ¶æ¹æ¬¡ç ç¨äºå岿«ç 追溯ï¼äº§çº¿ç¼ç /åç§°åä½åå¡«ï¼å¾éç»å®æçæ¶æ¹æ¬¡ç´æ¥è¿å
¥ç产ä¸ï¼ |
| | | boolean bindPallets = CollUtil.isNotEmpty(fillReqVO.getPalletIds()); |
| | | boolean hasBindings = hasBindings(fillReqVO); |
| | | MesProBatchDO updateObj = BeanUtils.toBean(fillReqVO, MesProBatchDO.class) |
| | | .setCode(code) |
| | | .setLineCode(line.getCode()) |
| | | .setLineName(line.getName()) |
| | | .setStatus(bindPallets ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | .setStatus(hasBindings ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | : MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | batchMapper.updateById(updateObj); |
| | | // 4. é建ç产人åé
ç½® |
| | |
| | | insertBatchWorkers(fillReqVO.getId(), fillReqVO.getWorkers()); |
| | | // 5. ç»å®æçï¼çº§èçææ£å¼æçç å¹¶å½å
¥æçä¸è¢ç ï¼å¤±è´¥æ´ä½åæ»ï¼ |
| | | bindPalletsToBatch(fillReqVO.getId(), fillReqVO.getPalletIds()); |
| | | bindTonBagsToBatch(fillReqVO.getId(), fillReqVO.getTonBagIds()); |
| | | // 6. çææ¹æ¬¡å®æ´æ§æè¦ï¼è¡¥å½æ£å¼ä¿¡æ¯åè¦çï¼ |
| | | integrityService.recordBatchIntegrity(fillReqVO.getId()); |
| | | } |
| | |
| | | updateObj.setLineCode(line.getCode()).setLineName(line.getName()); |
| | | } |
| | | // 4. æ´æ°æ¹æ¬¡ï¼å¾éç»å®æçæ¶æ¹æ¬¡ç´æ¥è¿å
¥ç产ä¸ï¼åæ¶å¾éä¸åéï¼å·²ç»å®æçä¸å¯è§£ç»ï¼ |
| | | boolean bindPallets = CollUtil.isNotEmpty(updateReqVO.getPalletIds()); |
| | | boolean hasBindings = hasBindings(updateReqVO); |
| | | updateObj.setCode(code); |
| | | if (bindPallets) { |
| | | if (hasBindings) { |
| | | updateObj.setStatus(MesProBatchStatusEnum.PRODUCING.getStatus()); |
| | | } |
| | | batchMapper.updateById(updateObj); |
| | |
| | | insertBatchWorkers(updateReqVO.getId(), updateReqVO.getWorkers()); |
| | | // 6. ç»å®æ°å¢å¾éçæçï¼çº§èçææ£å¼æçç å¹¶å½å
¥æçä¸è¢ç ï¼å¤±è´¥æ´ä½åæ»ï¼ |
| | | bindPalletsToBatch(updateReqVO.getId(), updateReqVO.getPalletIds()); |
| | | bindTonBagsToBatch(updateReqVO.getId(), updateReqVO.getTonBagIds()); |
| | | // 7. æè¦è¦çèå´å«åç§/产线/çäº§æ¥æ/è®¡åæ°éï¼ç¼è¾åéæ°çæé¿å
误æ¥ç¯¡æ¹ |
| | | integrityService.recordBatchIntegrity(updateReqVO.getId()); |
| | | } |
| | |
| | | @Override |
| | | public MesProBatchDO getBatch(Long id) { |
| | | return batchMapper.selectById(id); |
| | | } |
| | | |
| | | @Override |
| | | public String getBindingMode(Long id) { |
| | | if (!palletMapper.selectListByBatchId(id).isEmpty()) return "pallet"; |
| | | return bagCodeMapper.selectListByBatchId(id).stream() |
| | | .filter(bag -> bag.getPalletId() == null) |
| | | .map(MesProBagCodeDO::getItemId) |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .anyMatch(this::isTonItem) |
| | | ? "tonBag" : null; |
| | | } |
| | | |
| | | @Override |
| | |
| | | * çææ£å¼æçç 并级èå½å
¥æç䏿ªç»æ¹æ¬¡çè¢ç ï¼å¤±è´¥æ´ä½åæ» |
| | | */ |
| | | private Long resolveBindingItem(MesProBatchDO batch, MesProBatchSaveReqVO req) { |
| | | boolean palletsRequested = CollUtil.isNotEmpty(req.getPalletIds()); |
| | | boolean tonsRequested = CollUtil.isNotEmpty(req.getTonBagIds()); |
| | | if (palletsRequested && tonsRequested) throw bindingError("ç»å®æçåç»å®å¨è¢åªè½éæ©ä¸ç§"); |
| | | if (batch != null && (palletsRequested || tonsRequested)) { |
| | | String existingMode = getBindingMode(batch.getId()); |
| | | if ((tonsRequested && "pallet".equals(existingMode)) |
| | | || (palletsRequested && "tonBag".equals(existingMode))) |
| | | throw bindingError("è¯¥æ¹æ¬¡å·²ç»å®å¦ä¸ç§ç ï¼ç»å®æçåç»å®å¨è¢åªè½éæ©ä¸ç§"); |
| | | } |
| | | Long itemId = batch == null ? null : batch.getItemId(); |
| | | if (batch != null) { |
| | | for (Long existing : bagCodeMapper.selectDistinctItemIdsByBatchId(batch.getId())) |
| | |
| | | if (candidate == null) throw new cn.iocoder.yudao.framework.common.exception.ServiceException(400, "æç缺å°åç§ï¼è¯·å
ç»å®ååç§è¢ç "); |
| | | itemId = cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletItemResolver.merge(itemId, candidate); |
| | | } |
| | | // 请æ±éçåç§åªè½ä¸å·²ç»å®/å¾
ç»å®æçä¸è´ï¼ä¸è½éè¿ç¼è¾æ¹åæ¹æ¬¡åç§ã |
| | | if (tonsRequested) { |
| | | if (req.getTonBagIds().contains(null)) throw bindingError("è¯·éæ©ææçå¨è¢"); |
| | | List<Long> ids = req.getTonBagIds().stream().distinct().sorted().toList(); |
| | | List<MesProBagCodeDO> bags = bagCodeMapper.selectListByIdsForUpdate(ids); |
| | | if (bags.size() != ids.size()) throw bindingError("æéå¨è¢ä¸åå¨"); |
| | | for (MesProBagCodeDO bag : bags) { |
| | | if (bag.getBatchId() != null || bag.getPalletId() != null || !isTonItem(bag.getItemId())) |
| | | throw bindingError("åªè½ç»å®æªå½å
¥æ¹æ¬¡ã没ææçä¸è®¡éåä½ä¸ºå¨çè¢ç "); |
| | | itemId = cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletItemResolver.merge(itemId, bag.getItemId()); |
| | | } |
| | | } |
| | | // 请æ±éçåç§åªè½ä¸å·²ç»å®æå¾
ç»å®çæç/å¨è¢ä¸è´ï¼ä¸è½éè¿ç¼è¾æ¹åæ¹æ¬¡åç§ã |
| | | if (req.getItemId() != null && !Objects.equals(req.getItemId(), itemId)) |
| | | throw new cn.iocoder.yudao.framework.common.exception.ServiceException(400, "åç§ç±ç»å®æç带å
¥ï¼ä¸å¯ä¿®æ¹ä¸ºå
¶ä»åç§"); |
| | | throw bindingError("åç§ç±ç»å®æçæå¨è¢å¸¦å
¥ï¼ä¸å¯ä¿®æ¹ä¸ºå
¶ä»åç§"); |
| | | return itemId; |
| | | } |
| | | |
| | | private boolean hasBindings(MesProBatchSaveReqVO req) { |
| | | return CollUtil.isNotEmpty(req.getPalletIds()) || CollUtil.isNotEmpty(req.getTonBagIds()); |
| | | } |
| | | |
| | | private boolean isTonItem(Long itemId) { |
| | | if (itemId == null) return false; |
| | | MesMdmItemDO item = mdmItemService.getItem(itemId); |
| | | if (item == null || item.getUnitMeasureId() == null) return false; |
| | | var result = unitMeasureApi.getUnitMeasure(item.getUnitMeasureId()); |
| | | return result != null && result.isSuccess() && result.getData() != null |
| | | && "å¨".equals(StrUtil.trim(result.getData().getType())); |
| | | } |
| | | |
| | | private cn.iocoder.yudao.framework.common.exception.ServiceException bindingError(String message) { |
| | | return new cn.iocoder.yudao.framework.common.exception.ServiceException(400, message); |
| | | } |
| | | |
| | | private void bindTonBagsToBatch(Long batchId, List<Long> tonBagIds) { |
| | | if (CollUtil.isEmpty(tonBagIds)) return; |
| | | MesProBagCodeBindBatchReqVO req = new MesProBagCodeBindBatchReqVO(); |
| | | req.setBatchId(batchId); |
| | | req.setIds(tonBagIds); |
| | | bagCodeService.bindBatch(req); |
| | | } |
| | | |
| | | private void bindPalletsToBatch(Long batchId, List<Long> palletIds) { |
| | | if (CollUtil.isEmpty(palletIds)) { |
| | | return; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.approver; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.approver.MesQcApproverConfigDO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸äºº Service æ¥å£ |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | public interface MesQcApproverService { |
| | | |
| | | /** |
| | | * å建质æ£å®¡æ ¸äººé
ç½® |
| | | */ |
| | | Long createConfig(MesQcApproverConfigSaveReqVO reqVO); |
| | | |
| | | /** |
| | | * æ´æ°è´¨æ£å®¡æ ¸äººé
ç½® |
| | | */ |
| | | void updateConfig(MesQcApproverConfigSaveReqVO reqVO); |
| | | |
| | | /** |
| | | * å é¤è´¨æ£å®¡æ ¸äººé
ç½® |
| | | */ |
| | | void deleteConfig(Long id); |
| | | |
| | | /** |
| | | * è·å¾è´¨æ£å®¡æ ¸äººé
ç½® |
| | | */ |
| | | MesQcApproverConfigDO getConfig(Long id); |
| | | |
| | | /** |
| | | * è·å¾è´¨æ£å®¡æ ¸äººé
ç½®å页 |
| | | */ |
| | | PageResult<MesQcApproverConfigDO> getConfigPage(MesQcApproverConfigPageReqVO pageReqVO); |
| | | |
| | | /** |
| | | * å¤æç¨æ·æ¯å¦ä¸ºæå®è´¨æ£ç±»ååå®¡æ ¸èç¹çå®¡æ ¸äºº |
| | | */ |
| | | boolean isApprover(Integer qcType, Integer approveNode, Long userId); |
| | | |
| | | /** |
| | | * æ ¡éªç¨æ·æ¯å¦ä¸ºæå®è´¨æ£ç±»ååå®¡æ ¸èç¹çå®¡æ ¸äººï¼ä¸æ¯åæåºå¼å¸¸ |
| | | */ |
| | | void validateApprover(Integer qcType, Integer approveNode, Long userId); |
| | | |
| | | /** |
| | | * è·å¾æå®è´¨æ£ç±»ååå®¡æ ¸èç¹çå®¡æ ¸äººç¨æ· ID éå |
| | | */ |
| | | List<Long> getApproverUserIds(Integer qcType, Integer approveNode); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.approver; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.approver.vo.MesQcApproverConfigSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.approver.MesQcApproverConfigDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.approver.MesQcApproverConfigMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcApproveNodeEnum; |
| | | import cn.iocoder.yudao.module.system.api.permission.PermissionApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | | * MES è´¨æ£å®¡æ ¸äºº Service å®ç°ç±» |
| | | * |
| | | * @author è¶
级管çå |
| | | */ |
| | | @Service |
| | | @Validated |
| | | public class MesQcApproverServiceImpl implements MesQcApproverService { |
| | | |
| | | private static final String SUPER_ADMIN_ROLE = "super_admin"; |
| | | private static final Integer STATUS_ENABLE = 0; |
| | | |
| | | @Resource |
| | | private MesQcApproverConfigMapper approverConfigMapper; |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private PermissionApi permissionApi; |
| | | |
| | | @Override |
| | | public Long createConfig(MesQcApproverConfigSaveReqVO reqVO) { |
| | | validateConfigData(reqVO, null); |
| | | MesQcApproverConfigDO config = BeanUtils.toBean(reqVO, MesQcApproverConfigDO.class); |
| | | approverConfigMapper.insert(config); |
| | | return config.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void updateConfig(MesQcApproverConfigSaveReqVO reqVO) { |
| | | validateConfigExists(reqVO.getId()); |
| | | validateConfigData(reqVO, reqVO.getId()); |
| | | approverConfigMapper.updateById(BeanUtils.toBean(reqVO, MesQcApproverConfigDO.class)); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteConfig(Long id) { |
| | | validateConfigExists(id); |
| | | approverConfigMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public MesQcApproverConfigDO getConfig(Long id) { |
| | | return approverConfigMapper.selectById(id); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<MesQcApproverConfigDO> getConfigPage(MesQcApproverConfigPageReqVO pageReqVO) { |
| | | return approverConfigMapper.selectPage(pageReqVO); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isApprover(Integer qcType, Integer approveNode, Long userId) { |
| | | if (userId == null) { |
| | | return false; |
| | | } |
| | | // è¶
管ä¸åå®¡æ ¸äººé
ç½®éå¶ |
| | | if (permissionApi.hasAnyRoles(userId, SUPER_ADMIN_ROLE)) { |
| | | return true; |
| | | } |
| | | MesQcApproverConfigDO config = approverConfigMapper.selectByUnique(qcType, approveNode, userId); |
| | | return config != null && Objects.equals(config.getStatus(), STATUS_ENABLE); |
| | | } |
| | | |
| | | @Override |
| | | public void validateApprover(Integer qcType, Integer approveNode, Long userId) { |
| | | if (!isApprover(qcType, approveNode, userId)) { |
| | | throw exception(QC_APPROVER_NOT_CONFIGURED); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<Long> getApproverUserIds(Integer qcType, Integer approveNode) { |
| | | return approverConfigMapper.selectList(new LambdaQueryWrapperX<MesQcApproverConfigDO>() |
| | | .eq(MesQcApproverConfigDO::getQcType, qcType) |
| | | .eq(MesQcApproverConfigDO::getApproveNode, approveNode) |
| | | .eq(MesQcApproverConfigDO::getStatus, STATUS_ENABLE)) |
| | | .stream().map(MesQcApproverConfigDO::getUserId).toList(); |
| | | } |
| | | |
| | | private MesQcApproverConfigDO validateConfigExists(Long id) { |
| | | MesQcApproverConfigDO config = approverConfigMapper.selectById(id); |
| | | if (config == null) { |
| | | throw exception(QC_APPROVER_CONFIG_NOT_EXISTS); |
| | | } |
| | | return config; |
| | | } |
| | | |
| | | private void validateConfigData(MesQcApproverConfigSaveReqVO reqVO, Long excludeId) { |
| | | if (!MesQcApproveNodeEnum.isValidCombination(reqVO.getQcType(), reqVO.getApproveNode())) { |
| | | throw exception(QC_APPROVER_NODE_INVALID); |
| | | } |
| | | adminUserApi.validateUser(reqVO.getUserId()); |
| | | MesQcApproverConfigDO existed = approverConfigMapper.selectByUnique( |
| | | reqVO.getQcType(), reqVO.getApproveNode(), reqVO.getUserId()); |
| | | if (existed != null && !Objects.equals(existed.getId(), excludeId)) { |
| | | throw exception(QC_APPROVER_CONFIG_DUPLICATE); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | * @param id ç¼å· |
| | | */ |
| | | void finishOqc(Long id); |
| | | void retestOqc(cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRetestReqVO reqVO); |
| | | void salesApprove(Long id, boolean approved, String opinion); |
| | | void companyApprove(Long id, boolean approved, String opinion); |
| | | List<cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcActionDO> getActions(Long id); |
| | | |
| | | /** |
| | | * å é¤åºè´§æ£éªå |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.oqc; |
| | | |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.json.JSONUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcActionDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcActionMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; |
| | |
| | | import java.math.RoundingMode; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Set; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | |
| | | @Validated |
| | | public class MesQcOqcServiceImpl implements MesQcOqcService { |
| | | |
| | | private static final int WAIT_RETEST = 10, WAIT_SALES = 20, WAIT_COMPANY = 30, |
| | | RELEASED = 40, WAIT_SALES_FAIL = 50, WAIT_COMPANY_FAIL = 60, REJECTED = 70; |
| | | |
| | | @Resource |
| | | private MesQcOqcMapper oqcMapper; |
| | | @Resource |
| | | private MesQcOqcActionMapper actionMapper; |
| | | |
| | | @Resource |
| | | private MesQcTemplateItemService templateItemService; |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void finishOqc(Long id) { |
| | | // 1.1 æ ¡éªåå¨ + èç¨¿ç¶æ |
| | | MesQcOqcDO oqc = lock(id); |
| | | if (!MesQcStatusEnum.DRAFT.getStatus().equals(oqc.getStatus())) throw exception(QC_OQC_NOT_PREPARE); |
| | | MesQcOqcDO oqc = validateOqcStatusPrepare(id); |
| | | // 1.2 æ ¡éªæ£æµç»è®ºå¿
å¡« |
| | | if (oqc.getCheckResult() == null) { |
| | | throw exception(QC_OQC_CHECK_RESULT_EMPTY); |
| | | } |
| | | if (oqc.getUnqualifiedQuantity() != null && oqc.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0 |
| | | && MesQcCheckResultEnum.QUALIFIED.getType().equals(oqc.getCheckResult())) { |
| | | throw new IllegalArgumentException("åå¨ä¸åæ ¼åæ¶ï¼åºè´§æ£éªç»è®ºä¸è½ä¸ºåæ ¼"); |
| | | } |
| | | if ((oqc.getUnqualifiedQuantity() == null || oqc.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) == 0) |
| | | && !MesQcCheckResultEnum.QUALIFIED.getType().equals(oqc.getCheckResult())) { |
| | | throw new IllegalArgumentException("ä¸åæ ¼æ°é为 0 æ¶ï¼åºè´§æ£éªç»è®ºå¿
é¡»ä¸ºåæ ¼"); |
| | | } |
| | | // 1.3 æ ¡éªè³å°åå¨ä¸æ¡æ£æµç»æ |
| | | indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.OQC.getType()); |
| | | |
| | | // 2. æ´æ°ç¶æä¸ºå·²å®æ |
| | | MesQcOqcDO updateObj = new MesQcOqcDO() |
| | | .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()) |
| | | .setWorkflowStatus(MesQcCheckResultEnum.QUALIFIED.getType().equals(oqc.getCheckResult()) ? WAIT_SALES : WAIT_RETEST); |
| | | .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); |
| | | oqcMapper.updateById(updateObj); |
| | | recordAction(id, "INITIAL", oqc.getCheckResult(), null, oqc); |
| | | // éå®åºåºæç»ä»ä¸ºå¾
æ£ï¼å
¬å¸è´¨æ£å®¡æ¹éè¿åæååå¹¶å
许åç»åºåºã |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void retestOqc(MesQcOqcRetestReqVO req) { |
| | | MesQcOqcDO oqc = requireStatus(req.getId(), WAIT_RETEST); |
| | | if (req.getCheckQuantity().compareTo(req.getQualifiedQuantity().add(req.getUnqualifiedQuantity())) != 0) |
| | | throw new IllegalArgumentException("æ£æµæ°éå¿
é¡»çäºåæ ¼ä¸ä¸åæ ¼æ°éä¹å"); |
| | | if (req.getCheckQuantity().compareTo(oqc.getOutQuantity()) > 0) |
| | | throw new IllegalArgumentException("æ£æµæ°éä¸è½è¶
è¿åºè´§æ°é"); |
| | | if (!Set.of(1, 2).contains(req.getCheckResult())) throw new IllegalArgumentException("夿£ç»è®ºåªè½ä¸ºåæ ¼æä¸åæ ¼"); |
| | | boolean passed = req.getCheckResult() == 1; |
| | | if (passed != (req.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) == 0)) |
| | | throw new IllegalArgumentException("夿£ç»è®ºä¸ä¸åæ ¼æ°éä¸ä¸è´"); |
| | | if (!passed && (req.getOpinion() == null || req.getOpinion().isBlank())) |
| | | throw new IllegalArgumentException("夿£ä¸åæ ¼å¿
须填ååå "); |
| | | MesQcOqcDO update = new MesQcOqcDO().setId(req.getId()) |
| | | .setCheckQuantity(req.getCheckQuantity()).setQualifiedQuantity(req.getQualifiedQuantity()) |
| | | .setUnqualifiedQuantity(req.getUnqualifiedQuantity()).setCheckResult(req.getCheckResult()) |
| | | .setInspectDate(LocalDateTime.now()).setInspectorUserId(getLoginUserId()) |
| | | .setWorkflowStatus(passed ? WAIT_SALES : WAIT_SALES_FAIL); |
| | | oqcMapper.updateById(update); |
| | | recordAction(req.getId(), "RETEST", req.getCheckResult(), req.getOpinion(), update); |
| | | } |
| | | // 3. ä¸åæ ¼æ¶èªå¨å建 NCR |
| | | generateNcrIfNeeded(oqc); |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void salesApprove(Long id, boolean approved, String opinion) { |
| | | MesQcOqcDO oqc = lock(id); |
| | | if (!Set.of(WAIT_SALES, WAIT_SALES_FAIL).contains(oqc.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡éå®é¨å®¡æ¹"); |
| | | requireOpinion(opinion); |
| | | int next = approved ? (oqc.getWorkflowStatus() == WAIT_SALES ? WAIT_COMPANY : WAIT_COMPANY_FAIL) : WAIT_RETEST; |
| | | oqcMapper.updateById(new MesQcOqcDO().setId(id).setWorkflowStatus(next)); |
| | | recordAction(id, approved ? "SALES_APPROVE" : "SALES_REJECT", oqc.getCheckResult(), opinion, oqc); |
| | | // 4. å忥æºåæ® |
| | | writeBackSourceDoc(oqc); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void companyApprove(Long id, boolean approved, String opinion) { |
| | | MesQcOqcDO oqc = lock(id); |
| | | if (!Set.of(WAIT_COMPANY, WAIT_COMPANY_FAIL).contains(oqc.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡å
¬å¸è´¨æ£å®¡æ¹"); |
| | | requireOpinion(opinion); |
| | | if (approved) { |
| | | if (oqc.getWorkflowStatus() == WAIT_COMPANY_FAIL) generateNcrIfNeeded(oqc); |
| | | writeBackSourceDoc(oqc); |
| | | } |
| | | int next = approved ? (oqc.getWorkflowStatus() == WAIT_COMPANY ? RELEASED : REJECTED) : WAIT_RETEST; |
| | | oqcMapper.updateById(new MesQcOqcDO().setId(id).setWorkflowStatus(next)); |
| | | recordAction(id, approved ? "COMPANY_APPROVE" : "COMPANY_REJECT", oqc.getCheckResult(), opinion, oqc); |
| | | } |
| | | |
| | | private MesQcOqcDO lock(Long id) { |
| | | MesQcOqcDO oqc = oqcMapper.selectByIdForUpdate(id); |
| | | if (oqc == null) throw exception(QC_OQC_NOT_EXISTS); |
| | | return oqc; |
| | | } |
| | | |
| | | private MesQcOqcDO requireStatus(Long id, int status) { |
| | | MesQcOqcDO oqc = lock(id); |
| | | if (!Objects.equals(oqc.getWorkflowStatus(), status)) |
| | | throw new IllegalArgumentException("éå®è´¨æ£ç¶æå·²ååï¼è¯·å·æ°åéè¯"); |
| | | return oqc; |
| | | } |
| | | |
| | | private void requireOpinion(String opinion) { |
| | | if (opinion == null || opinion.isBlank()) throw new IllegalArgumentException("请填åå®¡æ¹æè§"); |
| | | } |
| | | |
| | | private void recordAction(Long id, String action, Integer result, String opinion, MesQcOqcDO snapshot) { |
| | | MesQcOqcActionDO event = new MesQcOqcActionDO(); |
| | | event.setOqcId(id);event.setAction(action);event.setResult(result);event.setOpinion(opinion); |
| | | java.util.Map<String, BigDecimal> quantities = new java.util.HashMap<>(); |
| | | quantities.put("checkQuantity", snapshot.getCheckQuantity()); |
| | | quantities.put("qualifiedQuantity", snapshot.getQualifiedQuantity()); |
| | | quantities.put("unqualifiedQuantity", snapshot.getUnqualifiedQuantity()); |
| | | event.setQuantitiesJson(JSONUtil.toJsonStr(quantities)); |
| | | event.setOperatorId(getLoginUserId());event.setCreateTime(LocalDateTime.now()); |
| | | actionMapper.insert(event); |
| | | } |
| | | |
| | | @Override |
| | | public List<MesQcOqcActionDO> getActions(Long id) { return actionMapper.selectByOqcId(id); } |
| | | |
| | | /** |
| | | * ä¸åæ ¼æ¶èªå¨å建 NCRï¼ä¸åæ ¼åå¤çåï¼ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.seedquality; |
| | | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedIndicatorRangeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedIndicatorRangeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality.MesQcSeedIndicatorRangeMapper; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.math.BigDecimal; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | public class MesQcSeedIndicatorRangeService { |
| | | private static final Set<String> CODES = Set.of("purity", "cleanliness", "germination_rate", "moisture"); |
| | | @Resource private MesQcSeedIndicatorRangeMapper mapper; |
| | | |
| | | public List<MesQcSeedIndicatorRangeDO> getRanges() { |
| | | return mapper.selectList().stream().filter(item -> CODES.contains(item.getIndicatorCode())).toList(); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void saveRanges(MesQcSeedIndicatorRangeSaveReqVO request) { |
| | | List<MesQcSeedIndicatorRangeSaveReqVO.Item> items = request.getRanges(); |
| | | if (items == null || items.size() != CODES.size() || items.stream().anyMatch(item -> item == null || item.getIndicatorCode() == null |
| | | || item.getMinValue() == null || item.getMaxValue() == null) |
| | | || !items.stream().map(MesQcSeedIndicatorRangeSaveReqVO.Item::getIndicatorCode) |
| | | .collect(Collectors.toSet()).equals(CODES)) |
| | | throw new IllegalArgumentException("å¿
须宿´é
置纯度ãå度ãåè½çãæ°´ååé¡¹ææ "); |
| | | for (MesQcSeedIndicatorRangeSaveReqVO.Item item : items) { |
| | | if (item.getMinValue().compareTo(BigDecimal.ZERO) < 0 || item.getMaxValue().compareTo(new BigDecimal("100")) > 0 |
| | | || item.getMinValue().compareTo(item.getMaxValue()) > 0) |
| | | throw new IllegalArgumentException("ææ åæ ¼èå´å¿
é¡»å¤äº 0â100 ä¸ä¸éä¸å¤§äºä¸éï¼" + item.getIndicatorCode()); |
| | | MesQcSeedIndicatorRangeDO row = new MesQcSeedIndicatorRangeDO(); |
| | | row.setIndicatorCode(item.getIndicatorCode()); |
| | | row.setMinValue(item.getMinValue()); |
| | | row.setMaxValue(item.getMaxValue()); |
| | | if (mapper.selectById(item.getIndicatorCode()) == null) mapper.insert(row); |
| | | else mapper.updateById(row); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | java.util.Map<String, Object> resolveScan(String code, String scanType); |
| | | java.util.Map<String, Object> submitGroup(cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityGroupSubmitReqVO reqVO); |
| | | void retest(Long id, cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO reqVO); |
| | | void retestBatch(cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityBatchRetestReqVO reqVO); |
| | | java.util.Map<String, Object> resolveRetestScope(String code, String scanType); |
| | | java.util.Map<String, Object> retestScope(cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityScopeRetestReqVO reqVO); |
| | | void processApprove(Long id, boolean approved, String opinion); |
| | | void companyApprove(Long id, boolean approved, String opinion); |
| | | void processApproveBatch(List<Long> ids, boolean approved, String opinion); |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstockbag.MesWmMaterialStockBagDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstockbag.MesWmMaterialStockBagMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeQcStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcApproveNodeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcApprovalTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockStateEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmWarehouseTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.approver.MesQcApproverService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.materialstockbag.MesWmMaterialStockBagService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | |
| | | @Service @Validated @Slf4j |
| | | public class MesQcSeedQualityServiceImpl implements MesQcSeedQualityService { |
| | | private static final Set<String> REQUIRED = Set.of("purity", "cleanliness", "germination_rate", "moisture"); |
| | | private static final int WAIT_RETEST = 10, WAIT_PROCESS = 20, WAIT_COMPANY = 30, |
| | | RELEASED = 40, WAIT_PROCESS_FAIL = 50, WAIT_COMPANY_FAIL = 60, SCRAPPED = 70; |
| | | private static final int WAIT_RETEST = 10, WAIT_PROCESS = 20, WAIT_INITIAL_FAIL_REVIEW = 25, WAIT_COMPANY = 30, |
| | | RELEASED = 40, WAIT_INITIAL_RECHECK = 50, WAIT_COMPANY_FAIL = 60, SCRAPPED = 70; |
| | | @Resource private MesQcSeedQualityMapper qualityMapper; |
| | | @Resource private MesQcApproverService approverService; |
| | | @Resource private MesQcSeedQualityActionMapper actionMapper; |
| | | @Resource private MesQcSeedQualityIndicatorMapper indicatorMapper; |
| | | @Resource private MesProBagCodeMapper bagCodeMapper; |
| | |
| | | .inspectedAt(LocalDateTime.now()).build(); |
| | | qualityMapper.insert(quality); |
| | | for (MesQcSeedQualitySubmitReqVO.Indicator item : reqVO.getIndicators()) { |
| | | if (item == null || item.getCode() == null || item.getValue() == null || item.getMinValue() == null || item.getMaxValue() == null) |
| | | throw new IllegalArgumentException("åé¡¹ææ ç宿µå¼åæ¬æ¬¡åæ ¼èå´å¿
须宿´"); |
| | | if (!REQUIRED.contains(item.getCode()) || !codes.add(item.getCode())) throw new IllegalArgumentException("ææ å¿
须为纯度ãå度ãåè½çãæ°´åä¸ä¸å¯éå¤"); |
| | | if (item.getMinValue().compareTo(item.getMaxValue()) > 0) throw new IllegalArgumentException("ææ ä¸éä¸è½å¤§äºä¸é"); |
| | | if (item.getValue().compareTo(BigDecimal.ZERO) < 0 || item.getValue().compareTo(new BigDecimal("100")) > 0 |
| | | || item.getMinValue().compareTo(BigDecimal.ZERO) < 0 || item.getMaxValue().compareTo(new BigDecimal("100")) > 0) |
| | | throw new IllegalArgumentException("ç¾åæ¯ææ å¿
é¡»å¤äº 0â100"); |
| | | if (item.getValue().compareTo(item.getMinValue()) < 0 || item.getValue().compareTo(item.getMaxValue()) > 0) passed = false; |
| | | indicatorMapper.insert(MesQcSeedQualityIndicatorDO.builder().qualityId(quality.getId()).indicatorCode(item.getCode()) |
| | | .value(item.getValue()).minValue(item.getMinValue()).maxValue(item.getMaxValue()).build()); |
| | |
| | | if (!codes.equals(REQUIRED)) throw new IllegalArgumentException("åé¡¹ææ ä¸å®æ´"); |
| | | if (!passed && StrUtil.isBlank(reqVO.getReason())) throw new IllegalArgumentException("è´¨æ£ä¸åæ ¼å¿
须填ååå "); |
| | | quality.setResult(passed ? 1 : 2); |
| | | quality.setWorkflowStatus(passed ? WAIT_PROCESS : WAIT_RETEST); |
| | | quality.setWorkflowStatus(passed ? WAIT_PROCESS : WAIT_INITIAL_FAIL_REVIEW); |
| | | qualityMapper.updateById(quality); |
| | | recordAction(quality.getId(), "INITIAL", quality.getResult(), reqVO.getReason(), reqVO.getIndicators()); |
| | | // 忣ä»
è®°å½ç»è®ºï¼è¢ä»ç卿ååºï¼å¾
夿£å两级审æ¹ååæ¾è¡ææ¥åºã |
| | | // 忣ä»
è®°å½ç»è®ºï¼è¢ä»ç卿ååºï¼å¾
åæ£å®¡æ ¸ã夿£åæç»å®¡æ ¸ååæ¾è¡ææ¥åºã |
| | | return quality.getId(); |
| | | } |
| | | |
| | |
| | | |
| | | @Override @Transactional(rollbackFor = Exception.class) |
| | | public void retest(Long id, cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO req) { |
| | | MesQcSeedQualityDO quality = requireStatus(id, WAIT_RETEST); |
| | | if (!Objects.equals(quality.getCode(), req.getCode())) throw new IllegalArgumentException("夿£è¢ç ä¸åè´¨æ£è®°å½ä¸ä¸è´"); |
| | | MesQcSeedQualityDO quality = qualityMapper.selectByIdForUpdate(id); |
| | | if (quality == null || !Set.of(WAIT_RETEST, WAIT_INITIAL_RECHECK).contains(quality.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½æäº¤å¤æ£ï¼è¯·å·æ°åéè¯"); |
| | | boolean initialRecheck = Objects.equals(quality.getWorkflowStatus(), WAIT_INITIAL_RECHECK); |
| | | if (!Objects.equals(quality.getCode(), req.getCode())) throw new IllegalArgumentException("æ£éªè¢ç ä¸åè´¨æ£è®°å½ä¸ä¸è´"); |
| | | boolean passed = validateIndicators(req.getIndicators()); |
| | | if (!passed && StrUtil.isBlank(req.getReason())) throw new IllegalArgumentException("夿£ä¸åæ ¼å¿
须填ååå "); |
| | | recordAction(id, "RETEST", passed ? 1 : 2, req.getReason(), req.getIndicators()); |
| | | qualityMapper.updateById(MesQcSeedQualityDO.builder().id(id).result(passed ? 1 : 2) |
| | | .reason(passed ? "" : req.getReason().trim()).retestResult(passed ? 1 : 2).retestedAt(LocalDateTime.now()) |
| | | if (!passed && StrUtil.isBlank(req.getReason())) throw new IllegalArgumentException("æ£éªä¸åæ ¼å¿
须填ååå "); |
| | | recordAction(id, initialRecheck ? "INITIAL_RECHECK" : "RETEST", passed ? 1 : 2, req.getReason(), req.getIndicators()); |
| | | MesQcSeedQualityDO update = MesQcSeedQualityDO.builder().id(id).result(passed ? 1 : 2) |
| | | .reason(passed ? "" : req.getReason().trim()) |
| | | .inspectorId(getLoginUserId()).inspectedAt(LocalDateTime.now()) |
| | | .workflowStatus(passed ? WAIT_PROCESS : WAIT_PROCESS_FAIL).build()); |
| | | .workflowStatus(initialRecheck ? (passed ? WAIT_PROCESS : WAIT_INITIAL_FAIL_REVIEW) |
| | | : (passed ? WAIT_COMPANY : WAIT_COMPANY_FAIL)).build(); |
| | | if (!initialRecheck) { |
| | | update.setRetestResult(passed ? 1 : 2); |
| | | update.setRetestedAt(LocalDateTime.now()); |
| | | } |
| | | qualityMapper.updateById(update); |
| | | // 页é¢ãå
¬å¼è¿½æº¯è¯»åä¸»ææ è¡¨ï¼åæ¥ä¸ºææ°ä¸æ¬¡æµå¼ï¼å次æµå¼å¨æä½çç表ä¿çã |
| | | Map<String, MesQcSeedQualityIndicatorDO> existing = new HashMap<>(); |
| | | for (MesQcSeedQualityIndicatorDO indicator : indicatorMapper.selectListByQualityId(id)) |
| | |
| | | } |
| | | |
| | | @Override @Transactional(rollbackFor = Exception.class) |
| | | public void retestBatch(cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityBatchRetestReqVO req) { |
| | | List<Long> ids = approvalIds(req.getIds()); |
| | | String batchCode = null; |
| | | Integer workflowStatus = null; |
| | | boolean first = true; |
| | | List<MesQcSeedQualityDO> qualities = new ArrayList<>(); |
| | | for (Long id : ids) { |
| | | MesQcSeedQualityDO quality = qualityMapper.selectByIdForUpdate(id); |
| | | if (quality == null || !Set.of(WAIT_RETEST, WAIT_INITIAL_RECHECK).contains(quality.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("æéè®°å½å
å«ä¸å¯æ£éªçç¶æï¼è¯·å·æ°åéè¯"); |
| | | if (StrUtil.isBlank(quality.getBatchCode())) |
| | | throw new IllegalArgumentException("è®°å½ç¼ºå°çäº§æ¹æ¬¡ï¼ä¸è½æ¹éè´¨æ£"); |
| | | if (first) { |
| | | batchCode = quality.getBatchCode(); |
| | | workflowStatus = quality.getWorkflowStatus(); |
| | | first = false; |
| | | } else if (!Objects.equals(batchCode, quality.getBatchCode()) || !Objects.equals(workflowStatus, quality.getWorkflowStatus())) { |
| | | throw new IllegalArgumentException("æ¹éè´¨æ£åªå
许åçäº§æ¹æ¬¡ãåæµç¨ç¶æçè®°å½"); |
| | | } |
| | | qualities.add(quality); |
| | | } |
| | | for (MesQcSeedQualityDO quality : qualities) { |
| | | cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO single = |
| | | new cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO(); |
| | | single.setCode(quality.getCode()); |
| | | single.setIndicators(req.getIndicators()); |
| | | single.setReason(req.getReason()); |
| | | retest(quality.getId(), single); |
| | | } |
| | | } |
| | | |
| | | private void checkRetestScanType(String scanType) { |
| | | if (!Set.of("PALLET", "BATCH").contains(scanType)) |
| | | throw new IllegalArgumentException("æ¹éè´¨æ£åªæ¯ææçç æçäº§æ¹æ¬¡ç "); |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> resolveRetestScope(String code, String scanType) { |
| | | checkRetestScanType(scanType); |
| | | Scope scope = scope(code, scanType, false); |
| | | if (scope.canceled()) throw new IllegalArgumentException("è´¨æ£å¯¹è±¡å·²ä½åº"); |
| | | List<String> codes = scope.bags().stream().filter(b -> !Integer.valueOf(30).equals(b.getStatus()) && b.getInboundEventId() != null) |
| | | .map(MesProBagCodeDO::getCode).toList(); |
| | | List<MesQcSeedQualityDO> qualities = codes.isEmpty() ? List.of() : qualityMapper.selectListByCodes(codes); |
| | | List<Long> retestIds = qualities.stream().filter(q -> Objects.equals(q.getWorkflowStatus(), WAIT_RETEST)) |
| | | .map(MesQcSeedQualityDO::getId).sorted().toList(); |
| | | List<Long> initialRecheckIds = qualities.stream().filter(q -> Objects.equals(q.getWorkflowStatus(), WAIT_INITIAL_RECHECK)) |
| | | .map(MesQcSeedQualityDO::getId).sorted().toList(); |
| | | long pendingProcessCount = qualities.stream().filter(q -> Objects.equals(q.getWorkflowStatus(), WAIT_PROCESS) |
| | | || Objects.equals(q.getWorkflowStatus(), WAIT_INITIAL_FAIL_REVIEW)).count(); |
| | | long pendingCompanyCount = qualities.stream().filter(q -> Objects.equals(q.getWorkflowStatus(), WAIT_COMPANY) |
| | | || Objects.equals(q.getWorkflowStatus(), WAIT_COMPANY_FAIL)).count(); |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("code", scope.code()); result.put("scanType", scanType); result.put("batchCode", scope.batchCode()); |
| | | result.put("totalCount", codes.size()); result.put("retestIds", retestIds); |
| | | result.put("initialRecheckIds", initialRecheckIds); |
| | | result.put("pendingProcessCount", pendingProcessCount); |
| | | result.put("pendingCompanyCount", pendingCompanyCount); |
| | | return result; |
| | | } |
| | | |
| | | @Override @Transactional(rollbackFor = Exception.class) |
| | | public Map<String, Object> retestScope(cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityScopeRetestReqVO req) { |
| | | checkRetestScanType(req.getScanType()); |
| | | if (!Set.of(WAIT_RETEST, WAIT_INITIAL_RECHECK).contains(req.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("æ¹éè´¨æ£ç¶ææ æ"); |
| | | List<Long> confirmed = approvalIds(req.getQualityIds()); |
| | | Scope scope = scope(req.getCode(), req.getScanType(), true); |
| | | if (scope.canceled()) throw new IllegalArgumentException("è´¨æ£å¯¹è±¡å·²ä½åº"); |
| | | List<MesProBagCodeDO> effective = scope.bags().stream() |
| | | .filter(b -> !Integer.valueOf(30).equals(b.getStatus()) && b.getInboundEventId() != null).toList(); |
| | | if (effective.isEmpty()) throw new IllegalArgumentException("å½åèå´æ²¡æå·²å
¥åºçææè¢ç "); |
| | | List<MesProBagCodeDO> locked = bagCodeMapper.selectListByIdsForUpdate(effective.stream().map(MesProBagCodeDO::getId).toList()); |
| | | if (locked.size() != effective.size() || locked.stream().anyMatch(b -> Integer.valueOf(30).equals(b.getStatus()) || b.getInboundEventId() == null)) |
| | | throw new IllegalArgumentException("è¢ç ç¶æå·²ååï¼è¯·éæ°æ«æ"); |
| | | Scope current = scope(req.getCode(), req.getScanType(), false); |
| | | Set<Long> currentIds = current.bags().stream().filter(b -> !Integer.valueOf(30).equals(b.getStatus()) && b.getInboundEventId() != null) |
| | | .map(MesProBagCodeDO::getId).collect(java.util.stream.Collectors.toSet()); |
| | | if (!currentIds.equals(new HashSet<>(locked.stream().map(MesProBagCodeDO::getId).toList()))) |
| | | throw new IllegalArgumentException("è¢ç å½å±å·²ååï¼è¯·éæ°æ«æ"); |
| | | List<MesQcSeedQualityDO> qualities = qualityMapper.selectListByCodesForUpdate(locked.stream().map(MesProBagCodeDO::getCode).toList()); |
| | | List<MesQcSeedQualityDO> pending = qualities.stream().filter(q -> Objects.equals(q.getWorkflowStatus(), req.getWorkflowStatus())) |
| | | .sorted(Comparator.comparing(MesQcSeedQualityDO::getId)).toList(); |
| | | if (pending.isEmpty() || !confirmed.equals(pending.stream().map(MesQcSeedQualityDO::getId).toList())) |
| | | throw new IllegalArgumentException("å¾
è´¨æ£æ¸
åå·²ååï¼è¯·éæ°æ«ææ ¸å¯¹"); |
| | | for (MesQcSeedQualityDO quality : pending) { |
| | | var single = new cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO(); |
| | | single.setCode(quality.getCode()); single.setIndicators(req.getIndicators()); single.setReason(req.getReason()); |
| | | retest(quality.getId(), single); |
| | | } |
| | | return Map.of("processedCount", pending.size()); |
| | | } |
| | | |
| | | @Override @Transactional(rollbackFor = Exception.class) |
| | | public void processApprove(Long id, boolean approved, String opinion) { |
| | | MesQcSeedQualityDO quality = qualityMapper.selectByIdForUpdate(id); |
| | | if (quality == null || !Set.of(WAIT_PROCESS, WAIT_PROCESS_FAIL).contains(quality.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡å å·¥é¨å®¡æ¹"); |
| | | if (StrUtil.isBlank(opinion)) throw new IllegalArgumentException("请填åå®¡æ¹æè§"); |
| | | int next = approved ? (quality.getWorkflowStatus() == WAIT_PROCESS ? WAIT_COMPANY : WAIT_COMPANY_FAIL) : WAIT_RETEST; |
| | | if (quality == null || !Set.of(WAIT_PROCESS, WAIT_INITIAL_FAIL_REVIEW).contains(quality.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡åæ£å®¡æ ¸"); |
| | | approverService.validateApprover(MesQcApprovalTypeEnum.SEED_QUALITY.getType(), |
| | | MesQcApproveNodeEnum.PROCESS.getNode(), getLoginUserId()); |
| | | if (!approved && StrUtil.isBlank(opinion)) throw new IllegalArgumentException("é©³åæ¶è¯·å¡«åå®¡æ¹æè§"); |
| | | int next = approved ? WAIT_RETEST : WAIT_INITIAL_RECHECK; |
| | | qualityMapper.updateById(MesQcSeedQualityDO.builder().id(id).workflowStatus(next) |
| | | .processApprovedAt(LocalDateTime.now()).build()); |
| | | recordAction(id, approved ? "PROCESS_APPROVE" : "PROCESS_REJECT", quality.getResult(), opinion, null); |
| | |
| | | public void companyApprove(Long id, boolean approved, String opinion) { |
| | | MesQcSeedQualityDO quality = qualityMapper.selectByIdForUpdate(id); |
| | | if (quality == null || !Set.of(WAIT_COMPANY, WAIT_COMPANY_FAIL).contains(quality.getWorkflowStatus())) |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡å
¬å¸è´¨æ£å®¡æ¹"); |
| | | if (StrUtil.isBlank(opinion)) throw new IllegalArgumentException("请填åå®¡æ¹æè§"); |
| | | throw new IllegalArgumentException("å½åç¶æä¸è½è¿è¡å¤æ£å®¡æ ¸"); |
| | | approverService.validateApprover(MesQcApprovalTypeEnum.SEED_QUALITY.getType(), |
| | | MesQcApproveNodeEnum.COMPANY.getNode(), getLoginUserId()); |
| | | if (!approved && StrUtil.isBlank(opinion)) throw new IllegalArgumentException("é©³åæ¶è¯·å¡«åå®¡æ¹æè§"); |
| | | if (approved) finalizeStock(quality, quality.getWorkflowStatus() == WAIT_COMPANY); |
| | | int next = approved ? (quality.getWorkflowStatus() == WAIT_COMPANY ? RELEASED : SCRAPPED) : WAIT_RETEST; |
| | | qualityMapper.updateById(MesQcSeedQualityDO.builder().id(id).workflowStatus(next) |
| | |
| | | || item.getValue() == null || item.getMinValue() == null || item.getMaxValue() == null) |
| | | throw new IllegalArgumentException("ææ å¿
须为纯度ãå度ãåè½çãæ°´åä¸ä¸å¯éå¤"); |
| | | if (item.getMinValue().compareTo(item.getMaxValue()) > 0) throw new IllegalArgumentException("ææ ä¸éä¸è½å¤§äºä¸é"); |
| | | if (item.getValue().compareTo(BigDecimal.ZERO) < 0 || item.getValue().compareTo(new BigDecimal("100")) > 0 |
| | | || item.getMinValue().compareTo(BigDecimal.ZERO) < 0 || item.getMaxValue().compareTo(new BigDecimal("100")) > 0) |
| | | throw new IllegalArgumentException("ç¾åæ¯ææ å¿
é¡»å¤äº 0â100"); |
| | | if (item.getValue().compareTo(item.getMinValue()) < 0 || item.getValue().compareTo(item.getMaxValue()) > 0) passed = false; |
| | | } |
| | | return passed; |
| | |
| | | |
| | | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; |
| | |
| | | o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); |
| | | o.setSourceLineId(sourceLineId); |
| | | o.setCheckResult(checkResult); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.TEN); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | }); |
| | | oqcMapper.insert(oqc); |
| | | |
| | |
| | | // æè¨ï¼éªè¯ç¶ææ´æ°ä¸ºå·²å®æ |
| | | MesQcOqcDO updatedOqc = oqcMapper.selectById(oqc.getId()); |
| | | assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedOqc.getStatus()); |
| | | assertEquals(20, updatedOqc.getWorkflowStatus()); |
| | | // 忣宿䏿¾è¡ï¼éå®é¨åå
¬å¸è´¨æ£å审æ¹åæååã |
| | | verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt()); |
| | | oqcService.salesApprove(oqc.getId(), true, "éå®é¨åæ"); |
| | | oqcService.companyApprove(oqc.getId(), true, "å
¬å¸è´¨æ£åæ"); |
| | | // æè¨ï¼éªè¯ååéå®åºåºåè¡ |
| | | verify(productSalesLineService).updateProductSalesLineWhenOqcFinish( |
| | | eq(sourceLineId), eq(oqc.getId()), eq(checkResult)); |
| | | } |
| | | |
| | | @Test |
| | | public void testFailedInitialRetestPassOnlyReleasesAfterBothApprovals() { |
| | | Long sourceLineId = randomLongId(); |
| | | MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { |
| | | o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); |
| | | o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); |
| | | o.setSourceLineId(sourceLineId); |
| | | o.setOutQuantity(java.math.BigDecimal.valueOf(100)); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.valueOf(9)); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ONE); |
| | | o.setCheckResult(2); |
| | | }); |
| | | oqcMapper.insert(oqc); |
| | | oqcService.finishOqc(oqc.getId()); |
| | | assertEquals(10, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verifyNoInteractions(ncrService); |
| | | verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt()); |
| | | |
| | | MesQcOqcRetestReqVO retest = new MesQcOqcRetestReqVO(); |
| | | retest.setId(oqc.getId()); |
| | | retest.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | retest.setQualifiedQuantity(java.math.BigDecimal.TEN); |
| | | retest.setUnqualifiedQuantity(java.math.BigDecimal.ZERO); |
| | | retest.setCheckResult(1); |
| | | oqcService.retestOqc(retest); |
| | | assertEquals(20, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | oqcService.salesApprove(oqc.getId(), true, "éå®é¨éè¿"); |
| | | assertEquals(30, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt()); |
| | | oqcService.companyApprove(oqc.getId(), true, "å
¬å¸è´¨æ£éè¿"); |
| | | assertEquals(40, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(sourceLineId, oqc.getId(), 1); |
| | | verifyNoInteractions(ncrService); |
| | | } |
| | | |
| | | @Test |
| | | public void testFailedRetestCreatesNcrOnlyAfterCompanyApproval() { |
| | | Long sourceLineId = randomLongId(); |
| | | MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { |
| | | o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); |
| | | o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); |
| | | o.setSourceLineId(sourceLineId); |
| | | o.setOutQuantity(java.math.BigDecimal.valueOf(100)); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.valueOf(9)); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ONE); |
| | | o.setCheckResult(2); |
| | | }); |
| | | oqcMapper.insert(oqc); |
| | | oqcService.finishOqc(oqc.getId()); |
| | | MesQcOqcRetestReqVO retest = new MesQcOqcRetestReqVO(); |
| | | retest.setId(oqc.getId()); |
| | | retest.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | retest.setQualifiedQuantity(java.math.BigDecimal.valueOf(8)); |
| | | retest.setUnqualifiedQuantity(java.math.BigDecimal.valueOf(2)); |
| | | retest.setCheckResult(2); |
| | | retest.setOpinion("夿£ä»ä¸åæ ¼"); |
| | | oqcService.retestOqc(retest); |
| | | assertEquals(50, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verifyNoInteractions(ncrService); |
| | | oqcService.salesApprove(oqc.getId(), true, "éå®é¨ç¡®è®¤ä¸åæ ¼"); |
| | | assertEquals(60, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verifyNoInteractions(ncrService); |
| | | oqcService.companyApprove(oqc.getId(), true, "å
¬å¸è´¨æ£ç¡®è®¤ä¸åæ ¼"); |
| | | assertEquals(70, oqcMapper.selectById(oqc.getId()).getWorkflowStatus()); |
| | | verify(ncrService).createNcr(any()); |
| | | verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(sourceLineId, oqc.getId(), 2); |
| | | } |
| | | |
| | | @Test |
| | |
| | | MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { |
| | | o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); |
| | | o.setCheckResult(1); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.TEN); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | o.setSourceDocType(null); |
| | | o.setSourceLineId(null); |
| | | }); |
| | |
| | | MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { |
| | | o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); |
| | | o.setCheckResult(1); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.TEN); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); |
| | | o.setSourceLineId(null); // èæ°æ® |
| | | }); |
| | | oqcMapper.insert(oqc); |
| | | |
| | | oqcService.finishOqc(oqc.getId()); |
| | | oqcService.salesApprove(oqc.getId(), true, "éå®é¨åæ"); |
| | | assertThrows(IllegalArgumentException.class, () -> oqcService.companyApprove(oqc.getId(), true, "å
¬å¸è´¨æ£åæ")); |
| | | // è°ç¨ï¼å¹¶æè¨å¼å¸¸ |
| | | assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId())); |
| | | } |
| | | |
| | | @Test |
| | |
| | | MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { |
| | | o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); |
| | | o.setCheckResult(1); |
| | | o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO); |
| | | o.setQualifiedQuantity(java.math.BigDecimal.TEN); |
| | | o.setCheckQuantity(java.math.BigDecimal.TEN); |
| | | o.setSourceDocType(99999); // æ æ³è¯å«çç±»å |
| | | o.setSourceLineId(randomLongId()); |
| | | }); |
| | | oqcMapper.insert(oqc); |
| | | |
| | | oqcService.finishOqc(oqc.getId()); |
| | | oqcService.salesApprove(oqc.getId(), true, "éå®é¨åæ"); |
| | | assertThrows(IllegalArgumentException.class, () -> oqcService.companyApprove(oqc.getId(), true, "å
¬å¸è´¨æ£åæ")); |
| | | // è°ç¨ï¼å¹¶æè¨å¼å¸¸ |
| | | assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId())); |
| | | } |
| | | |
| | | @Test |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.seedquality; |
| | | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedIndicatorRangeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedIndicatorRangeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality.MesQcSeedIndicatorRangeMapper; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | import static org.mockito.Mockito.*; |
| | | |
| | | class MesQcSeedIndicatorRangeServiceTest { |
| | | private final MesQcSeedIndicatorRangeService service = new MesQcSeedIndicatorRangeService(); |
| | | private final MesQcSeedIndicatorRangeMapper mapper = mock(MesQcSeedIndicatorRangeMapper.class); |
| | | |
| | | @Test |
| | | void savesTemplateWithoutRestrictingActualInspection() { |
| | | ReflectionTestUtils.setField(service, "mapper", mapper); |
| | | MesQcSeedIndicatorRangeSaveReqVO request = new MesQcSeedIndicatorRangeSaveReqVO(); |
| | | request.setRanges(List.of(item("purity"), item("cleanliness"), item("germination_rate"), item("moisture"))); |
| | | service.saveRanges(request); |
| | | verify(mapper, times(4)).insert(any(MesQcSeedIndicatorRangeDO.class)); |
| | | } |
| | | |
| | | private MesQcSeedIndicatorRangeSaveReqVO.Item item(String code) { |
| | | MesQcSeedIndicatorRangeSaveReqVO.Item row = new MesQcSeedIndicatorRangeSaveReqVO.Item(); |
| | | row.setIndicatorCode(code); |
| | | row.setMinValue(new BigDecimal("90")); |
| | | row.setMaxValue(new BigDecimal("100")); |
| | | return row; |
| | | } |
| | | } |
| | |
| | | var proxy=(MesQcSeedQualityService)factory.getProxy(); |
| | | assertThrows(IllegalStateException.class,()->proxy.submitGroup(req));assertEquals(0,jdbc.queryForObject("SELECT COUNT(*) FROM qc_result",Integer.class)); |
| | | } |
| | | @Test void retestScopePreviewSeparatesWorkflowStages() { |
| | | when(qualities.selectListByCodes(any())).thenReturn(List.of( |
| | | MesQcSeedQualityDO.builder().id(11L).code("B1").workflowStatus(10).build(), |
| | | MesQcSeedQualityDO.builder().id(12L).code("B2").workflowStatus(50).build())); |
| | | var result = service.resolveRetestScope("PALLET-BUS", "PALLET"); |
| | | assertEquals(List.of(11L), result.get("retestIds")); |
| | | assertEquals(List.of(12L), result.get("initialRecheckIds")); |
| | | } |
| | | @Test void retestScopeRejectsStaleConfirmedList() { |
| | | when(qualities.selectListByCodesForUpdate(any())).thenReturn(List.of( |
| | | MesQcSeedQualityDO.builder().id(11L).code("B1").workflowStatus(10).build(), |
| | | MesQcSeedQualityDO.builder().id(12L).code("B2").workflowStatus(10).build())); |
| | | var request = new MesQcSeedQualityScopeRetestReqVO(); |
| | | request.setCode("BATCH-BUS"); request.setScanType("BATCH"); request.setWorkflowStatus(10); |
| | | request.setQualityIds(List.of(11L)); request.setIndicators(List.of()); |
| | | assertThrows(IllegalArgumentException.class, () -> service.retestScope(request)); |
| | | verify(service, never()).retest(anyLong(), any()); |
| | | } |
| | | @Test void retestScopeProcessesAllConfirmedBags() { |
| | | when(qualities.selectListByCodesForUpdate(any())).thenReturn(List.of( |
| | | MesQcSeedQualityDO.builder().id(11L).code("B1").workflowStatus(10).build(), |
| | | MesQcSeedQualityDO.builder().id(12L).code("B2").workflowStatus(10).build())); |
| | | doNothing().when(service).retest(anyLong(), any()); |
| | | var request = new MesQcSeedQualityScopeRetestReqVO(); |
| | | request.setCode("BATCH-BUS"); request.setScanType("BATCH"); request.setWorkflowStatus(10); |
| | | request.setQualityIds(List.of(11L, 12L)); request.setIndicators(List.of()); |
| | | assertEquals(2, service.retestScope(request).get("processedCount")); |
| | | verify(service, times(2)).retest(anyLong(), any()); |
| | | } |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.mes.service.qc.seedquality; |
| | | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedQualityDO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedQualityBatchRetestReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality.MesQcSeedQualityActionMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality.MesQcSeedQualityMapper; |
| | | import cn.iocoder.yudao.module.mes.service.qc.approver.MesQcApproverService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.mockito.ArgumentCaptor; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | import java.util.List; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.*; |
| | | import static org.mockito.Mockito.*; |
| | |
| | | private final MesQcSeedQualityMapper qualityMapper = mock(MesQcSeedQualityMapper.class); |
| | | private final MesQcSeedQualityActionMapper actionMapper = mock(MesQcSeedQualityActionMapper.class); |
| | | private final MesWmTransactionService transactionService = mock(MesWmTransactionService.class); |
| | | private final MesQcApproverService approverService = mock(MesQcApproverService.class); |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | | ReflectionTestUtils.setField(service, "qualityMapper", qualityMapper); |
| | | ReflectionTestUtils.setField(service, "actionMapper", actionMapper); |
| | | ReflectionTestUtils.setField(service, "wmTransactionService", transactionService); |
| | | ReflectionTestUtils.setField(service, "approverService", approverService); |
| | | } |
| | | |
| | | @Test |
| | | void failedRetestNeedsBothApprovalsBeforeDisposal() { |
| | | void initialApprovalOnlyQueuesRetestAndFailedRetestCanReturnToRetest() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").result(2).workflowStatus(50).build(), |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").result(2).workflowStatus(20).build(), |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").result(2).workflowStatus(60).build()); |
| | | service.processApprove(1L, true, "确认ä¸åæ ¼ï¼éå
¬å¸è´¨æ£å®¡æ¹"); |
| | | service.processApprove(1L, true, ""); |
| | | verifyNoInteractions(transactionService); |
| | | service.companyApprove(1L, false, "è¿å夿£"); |
| | | service.companyApprove(1L, false, "夿£ä¸åæ ¼ï¼éæ°åæ ·"); |
| | | ArgumentCaptor<MesQcSeedQualityDO> update = ArgumentCaptor.forClass(MesQcSeedQualityDO.class); |
| | | verify(qualityMapper, times(2)).updateById(update.capture()); |
| | | assertEquals(60, update.getAllValues().get(0).getWorkflowStatus()); |
| | | assertEquals(10, update.getAllValues().get(0).getWorkflowStatus()); |
| | | assertEquals(10, update.getAllValues().get(1).getWorkflowStatus()); |
| | | verifyNoInteractions(transactionService); |
| | | } |
| | | |
| | | @Test |
| | | void rejectedInitialInspectionNeedsRecheck() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").result(2).workflowStatus(25).build()); |
| | | service.processApprove(1L, false, "åæ£æ ·æ¬æ æï¼éæ°æ£æµ"); |
| | | ArgumentCaptor<MesQcSeedQualityDO> update = ArgumentCaptor.forClass(MesQcSeedQualityDO.class); |
| | | verify(qualityMapper).updateById(update.capture()); |
| | | assertEquals(50, update.getValue().getWorkflowStatus()); |
| | | verifyNoInteractions(transactionService); |
| | | } |
| | | |
| | | @Test |
| | | void rejectionRequiresOpinion() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).workflowStatus(20).build()); |
| | | assertEquals("é©³åæ¶è¯·å¡«åå®¡æ¹æè§", assertThrows(IllegalArgumentException.class, |
| | | () -> service.processApprove(1L, false, " ")).getMessage()); |
| | | verify(qualityMapper, never()).updateById(any(MesQcSeedQualityDO.class)); |
| | | verifyNoInteractions(actionMapper, transactionService); |
| | | } |
| | | |
| | | @Test |
| | | void cannotRetestBeforeInitialReview() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").workflowStatus(25).build()); |
| | | assertThrows(IllegalArgumentException.class, |
| | | () -> service.retest(1L, new MesQcSeedQualityRetestReqVO())); |
| | | verify(qualityMapper, never()).updateById(any(MesQcSeedQualityDO.class)); |
| | | verifyNoInteractions(transactionService, actionMapper); |
| | | } |
| | | |
| | | @Test |
| | | void batchRetestRejectsDifferentProductionBatchesBeforeAnyWrite() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).code("B1").batchCode("A").workflowStatus(10).build()); |
| | | when(qualityMapper.selectByIdForUpdate(2L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(2L).code("B2").batchCode("B").workflowStatus(10).build()); |
| | | MesQcSeedQualityBatchRetestReqVO request = new MesQcSeedQualityBatchRetestReqVO(); |
| | | request.setIds(List.of(1L, 2L)); |
| | | assertThrows(IllegalArgumentException.class, () -> service.retestBatch(request)); |
| | | verify(qualityMapper, never()).updateById(any(MesQcSeedQualityDO.class)); |
| | | verifyNoInteractions(transactionService, actionMapper); |
| | | } |
| | | |
| | | @Test |
| | | void skipsApprovalWhenStatusChanged() { |
| | | when(qualityMapper.selectByIdForUpdate(1L)).thenReturn( |
| | | MesQcSeedQualityDO.builder().id(1L).workflowStatus(40).build()); |
| | |
| | | "inspect_date" timestamp DEFAULT NULL, |
| | | "inspector_user_id" bigint DEFAULT NULL, |
| | | "status" tinyint NOT NULL DEFAULT 0, |
| | | "workflow_status" tinyint NOT NULL DEFAULT 0, |
| | | "remark" varchar(500) DEFAULT '', |
| | | "creator" varchar(64) DEFAULT '', |
| | | "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | |
| | | PRIMARY KEY ("id") |
| | | ); |
| | | |
| | | CREATE TABLE IF NOT EXISTS "mes_qc_oqc_action" ( |
| | | -- ---------------------------- |
| | | -- MES è´¨æ£å®¡æ ¸äººé
ç½® |
| | | -- ---------------------------- |
| | | CREATE TABLE IF NOT EXISTS "mes_qc_approver_config" ( |
| | | "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, |
| | | "oqc_id" bigint NOT NULL, |
| | | "action" varchar(32) NOT NULL, |
| | | "result" tinyint DEFAULT NULL, |
| | | "opinion" varchar(500) DEFAULT NULL, |
| | | "quantities_json" varchar(4000) DEFAULT NULL, |
| | | "operator_id" bigint DEFAULT NULL, |
| | | "qc_type" tinyint NOT NULL, |
| | | "approve_node" tinyint NOT NULL, |
| | | "user_id" bigint NOT NULL, |
| | | "status" tinyint NOT NULL DEFAULT 0, |
| | | "remark" varchar(255) DEFAULT NULL, |
| | | "creator" varchar(64) DEFAULT '', |
| | | "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | "updater" varchar(64) DEFAULT '', |
| | | "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | "deleted" bit NOT NULL DEFAULT FALSE, |
| | | "tenant_id" bigint NOT NULL DEFAULT 0, |
| | | PRIMARY KEY ("id") |
| | | ); |
| | | |