feat(mes): 添加销售出库扫码拣货功能
- 新增销售出库扫码拣货相关错误码定义
- 在袋码和托盘码实体中添加销售出库相关字段
- 实现袋码和托盘码的出库标记和清除功能
- 添加库存状态字段并实现状态更新逻辑
- 新增销售出库扫码拣货控制器接口
- 实现扫码拣货业务逻辑和服务方法
- 添加数据库表结构变更SQL脚本
- 创建扫码拣货请求和响应对象
- 完善销售出库明细中袋码和托盘码关联字段
已删除100个文件
已添加24个文件
已修改22个文件
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f1e4]: |
| | | - generic [ref=f1e5]: |
| | | - generic [ref=f1e6]: |
| | | - generic [ref=f1e7]: |
| | | - generic: |
| | | - button [ref=f1e8] [cursor=pointer] |
| | | - button [ref=f1e10] [cursor=pointer] |
| | | - button [ref=f1e12] [cursor=pointer] |
| | | - button [ref=f1e14] [cursor=pointer] |
| | | - button [ref=f1e16] [cursor=pointer] |
| | | - button [ref=f1e18] [cursor=pointer] |
| | | - button [ref=f1e22] [cursor=pointer] |
| | | - button [ref=f1e24] [cursor=pointer] |
| | | - button [ref=f1e31] [cursor=pointer] |
| | | - button [ref=f1e35] [cursor=pointer] |
| | | - button "light" [active] [ref=f1e236] [cursor=pointer] |
| | | - generic [ref=f1e50]: |
| | | - generic [ref=f1e79]: |
| | | - generic [ref=f1e88]: |
| | | - generic [ref=f1e89]: æ´ |
| | | - strong [ref=f1e90]: 26.8°C |
| | | - generic [ref=f1e94]: |
| | | - generic [ref=f1e95]: 湿度 |
| | | - strong [ref=f1e96]: 68% |
| | | - generic [ref=f1e104]: |
| | | - generic [ref=f1e105]: é鍿¦ç |
| | | - strong [ref=f1e106]: 20% |
| | | - generic [ref=f1e111]: |
| | | - generic [ref=f1e112]: å±±ä¸ç |
| | | - strong [ref=f1e113]: æµåå¸ |
| | | - generic [ref=f1e114]: |
| | | - generic [ref=f1e115]: |
| | | - generic [ref=f1e125]: |
| | | - generic [ref=f1e126]: ç§æ¤ä¸æ°ååå¹³å° |
| | | - generic [ref=f1e127]: AGRICULTURE DIGITAL PLATFORM |
| | | - generic [ref=f1e128]: æ°åèµè½åä¸ Â· ç§æå¼é¢æªæ¥ |
| | | - generic [ref=f1e132]: |
| | | - generic "å¹³å°è¿è¡æ¦è§" [ref=f1e133]: |
| | | - generic [ref=f1e139]: |
| | | - text: ç§æ¤é¢ç§¯ |
| | | - generic [ref=f1e140]: 12,580亩 |
| | | - generic [ref=f1e141]: è¾æ¨æ¥ â 2.35% |
| | | - generic [ref=f1e148]: |
| | | - text: å¨çº¿è®¾å¤ |
| | | - generic [ref=f1e149]: 1,286å° |
| | | - generic [ref=f1e150]: è¾æ¨æ¥ â 5.21% |
| | | - generic [ref=f1e156]: |
| | | - text: 仿¥çæº |
| | | - generic [ref=f1e157]: 328亩 |
| | | - generic [ref=f1e158]: è¾æ¨æ¥ â 1.15% |
| | | - generic [ref=f1e164]: |
| | | - text: AI é¢è¦ |
| | | - generic [ref=f1e165]: 6æ¡ |
| | | - generic [ref=f1e166]: è¾æ¨æ¥ â 12.50% |
| | | - generic [ref=f1e167]: |
| | | - generic [ref=f1e168]: |
| | | - generic [ref=f1e169]: å壤墿
çæµ |
| | | - generic [ref=f1e170]: |
| | | - strong [ref=f1e173]: 68.5% |
| | | - generic [ref=f1e174]: å壤湿度 |
| | | - img [ref=f1e175]: |
| | | - generic [ref=f1e177]: |
| | | - generic [ref=f1e178]: 100% |
| | | - generic [ref=f1e179]: 50% |
| | | - generic [ref=f1e180]: 0% |
| | | - generic [ref=f1e183]: |
| | | - generic [ref=f1e184]: 00:00 |
| | | - generic [ref=f1e185]: 06:00 |
| | | - generic [ref=f1e186]: 12:00 |
| | | - generic [ref=f1e187]: 18:00 |
| | | - generic [ref=f1e188]: 24:00 |
| | | - generic [ref=f1e189]: |
| | | - generic [ref=f1e190]: AI æºè½åæ |
| | | - paragraph [ref=f1e194]: å½åä½ç©é¿å¿è¯å¥½ï¼å壤墿
éå®ï¼æªæ¥3å¤©æ ææ¾éé¨ï¼å»ºè®®éæ¶çæºï¼ä¿è¯ä½ç©ç¨³äº§é«äº§ã |
| | | - generic [ref=f1e195]: |
| | | - generic [ref=f1e196]: © 2026 ç§æ¤ä¸æ°ååå¹³å° çæææ |
| | | - generic [ref=f1e197]: é²ICPå¤2026001234å·-1 |
| | | - generic [ref=f1e198] [cursor=pointer]: éç§æ¿ç |
| | | - generic [ref=f1e199]: "|" |
| | | - generic [ref=f1e200] [cursor=pointer]: ç¨æ·åè®® |
| | | - generic [ref=f1e204]: |
| | | - generic [ref=f1e205]: |
| | | - heading "欢è¿åæ¥" [level=2] [ref=f1e206] |
| | | - paragraph [ref=f1e207]: |
| | | - generic [ref=f1e208]: ç»å½ç§æ¤ä¸æ°ååå¹³å°ï¼å¼å¯æºæ
§ç§æ¤ |
| | | - generic [ref=f1e210]: |
| | | - textbox "请è¾å
¥ç¨æ·å" [ref=f1e216]: admin |
| | | - generic [ref=f1e222]: |
| | | - textbox "请è¾å
¥å¯ç " [ref=f1e223]: admin123 |
| | | - generic [ref=f1e224] [cursor=pointer] |
| | | - generic [ref=f1e232]: |
| | | - checkbox "è®°ä½è´¦å·" [ref=f1e233] [cursor=pointer] |
| | | - generic [ref=f1e234] [cursor=pointer]: è®°ä½è´¦å· |
| | | - button "login" [ref=f1e235] [cursor=pointer]: ç»å½ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f1e4]: |
| | | - generic [ref=f1e5]: |
| | | - generic [ref=f1e6]: |
| | | - generic [ref=f1e7]: |
| | | - generic: |
| | | - button [ref=f1e8] [cursor=pointer] |
| | | - button [ref=f1e10] [cursor=pointer] |
| | | - button [ref=f1e12] [cursor=pointer] |
| | | - button [ref=f1e14] [cursor=pointer] |
| | | - button [ref=f1e16] [cursor=pointer] |
| | | - button [ref=f1e18] [cursor=pointer] |
| | | - button [ref=f1e22] [cursor=pointer] |
| | | - button [ref=f1e24] [cursor=pointer] |
| | | - button [ref=f1e31] [cursor=pointer] |
| | | - button [ref=f1e35] [cursor=pointer] |
| | | - button "light" [ref=f1e236] [cursor=pointer] |
| | | - generic [ref=f1e50]: |
| | | - generic [ref=f1e79]: |
| | | - generic [ref=f1e88]: |
| | | - generic [ref=f1e89]: æ´ |
| | | - strong [ref=f1e90]: 26.8°C |
| | | - generic [ref=f1e94]: |
| | | - generic [ref=f1e95]: 湿度 |
| | | - strong [ref=f1e96]: 68% |
| | | - generic [ref=f1e104]: |
| | | - generic [ref=f1e105]: é鍿¦ç |
| | | - strong [ref=f1e106]: 20% |
| | | - generic [ref=f1e111]: |
| | | - generic [ref=f1e112]: å±±ä¸ç |
| | | - strong [ref=f1e113]: æµåå¸ |
| | | - generic [ref=f1e114]: |
| | | - generic [ref=f1e115]: |
| | | - generic [ref=f1e125]: |
| | | - generic [ref=f1e126]: ç§æ¤ä¸æ°ååå¹³å° |
| | | - generic [ref=f1e127]: AGRICULTURE DIGITAL PLATFORM |
| | | - generic [ref=f1e128]: æ°åèµè½åä¸ Â· ç§æå¼é¢æªæ¥ |
| | | - generic [ref=f1e132]: |
| | | - generic "å¹³å°è¿è¡æ¦è§" [ref=f1e133]: |
| | | - generic [ref=f1e139]: |
| | | - text: ç§æ¤é¢ç§¯ |
| | | - generic [ref=f1e140]: 12,580亩 |
| | | - generic [ref=f1e141]: è¾æ¨æ¥ â 2.35% |
| | | - generic [ref=f1e148]: |
| | | - text: å¨çº¿è®¾å¤ |
| | | - generic [ref=f1e149]: 1,286å° |
| | | - generic [ref=f1e150]: è¾æ¨æ¥ â 5.21% |
| | | - generic [ref=f1e156]: |
| | | - text: 仿¥çæº |
| | | - generic [ref=f1e157]: 328亩 |
| | | - generic [ref=f1e158]: è¾æ¨æ¥ â 1.15% |
| | | - generic [ref=f1e164]: |
| | | - text: AI é¢è¦ |
| | | - generic [ref=f1e165]: 6æ¡ |
| | | - generic [ref=f1e166]: è¾æ¨æ¥ â 12.50% |
| | | - generic [ref=f1e167]: |
| | | - generic [ref=f1e168]: |
| | | - generic [ref=f1e169]: å壤墿
çæµ |
| | | - generic [ref=f1e170]: |
| | | - strong [ref=f1e173]: 68.5% |
| | | - generic [ref=f1e174]: å壤湿度 |
| | | - img [ref=f1e175]: |
| | | - generic [ref=f1e177]: |
| | | - generic [ref=f1e178]: 100% |
| | | - generic [ref=f1e179]: 50% |
| | | - generic [ref=f1e180]: 0% |
| | | - generic [ref=f1e183]: |
| | | - generic [ref=f1e184]: 00:00 |
| | | - generic [ref=f1e185]: 06:00 |
| | | - generic [ref=f1e186]: 12:00 |
| | | - generic [ref=f1e187]: 18:00 |
| | | - generic [ref=f1e188]: 24:00 |
| | | - generic [ref=f1e189]: |
| | | - generic [ref=f1e190]: AI æºè½åæ |
| | | - paragraph [ref=f1e194]: å½åä½ç©é¿å¿è¯å¥½ï¼å壤墿
éå®ï¼æªæ¥3å¤©æ ææ¾éé¨ï¼å»ºè®®éæ¶çæºï¼ä¿è¯ä½ç©ç¨³äº§é«äº§ã |
| | | - generic [ref=f1e195]: |
| | | - generic [ref=f1e196]: © 2026 ç§æ¤ä¸æ°ååå¹³å° çæææ |
| | | - generic [ref=f1e197]: é²ICPå¤2026001234å·-1 |
| | | - generic [ref=f1e198] [cursor=pointer]: éç§æ¿ç |
| | | - generic [ref=f1e199]: "|" |
| | | - generic [ref=f1e200] [cursor=pointer]: ç¨æ·åè®® |
| | | - generic [ref=f1e204]: |
| | | - generic [ref=f1e205]: |
| | | - heading "欢è¿åæ¥" [level=2] [ref=f1e206] |
| | | - paragraph [ref=f1e207]: |
| | | - generic [ref=f1e208]: ç»å½ç§æ¤ä¸æ°ååå¹³å°ï¼å¼å¯æºæ
§ç§æ¤ |
| | | - generic [ref=f1e210]: |
| | | - textbox "请è¾å
¥ç¨æ·å" [ref=f1e216]: admin |
| | | - generic [ref=f1e222]: |
| | | - textbox "请è¾å
¥å¯ç " [ref=f1e223]: admin123 |
| | | - generic [ref=f1e224] [cursor=pointer] |
| | | - generic [ref=f1e232]: |
| | | - checkbox "è®°ä½è´¦å·" [ref=f1e233] [cursor=pointer] |
| | | - generic [ref=f1e234] [cursor=pointer]: è®°ä½è´¦å· |
| | | - button "login" [disabled]: ç»å½ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f1e237]: |
| | | - complementary [ref=f1e239]: |
| | | - generic [ref=f1e240]: |
| | | - generic [ref=f1e241] [cursor=pointer] |
| | | - link "å·¥ä¸AIæºé å¹³å° å·¥ä¸AIæºé å¹³å°" [ref=f1e246] [cursor=pointer]: |
| | | - /url: javascript:void 0 |
| | | - img "å·¥ä¸AIæºé å¹³å°" [ref=f1e249] |
| | | - generic [ref=f1e250]: å·¥ä¸AIæºé å¹³å° |
| | | - menu [ref=f1e253]: |
| | | - menuitem "é¦é¡µ" [ref=f1e254] [cursor=pointer] |
| | | - listitem [ref=f1e259]: |
| | | - generic [ref=f1e260] [cursor=pointer]: åºç¡æ°æ® |
| | | - listitem [ref=f1e268]: |
| | | - generic [ref=f1e269] [cursor=pointer]: ä»å¨ç©æµ |
| | | - listitem [ref=f1e277]: |
| | | - generic [ref=f1e278] [cursor=pointer]: ä¸è¢ä¸ç 管ç |
| | | - listitem [ref=f1e284]: |
| | | - generic [ref=f1e285] [cursor=pointer]: è´¨é管ç |
| | | - listitem [ref=f1e291]: |
| | | - generic [ref=f1e292] [cursor=pointer]: ç³»ç»ç®¡ç |
| | | - generic [ref=f1e299] [cursor=pointer] |
| | | - generic [ref=f1e304]: |
| | | - generic [ref=f1e305]: |
| | | - banner [ref=f1e306]: |
| | | - button [ref=f1e307] [cursor=pointer] |
| | | - button [ref=f1e310] [cursor=pointer] |
| | | - navigation "breadcrumb" [ref=f1e315]: |
| | | - list [ref=f1e316]: |
| | | - listitem [ref=f1e317]: |
| | | - link "é¦é¡µ" [disabled] [ref=f1e318] |
| | | - generic [ref=f1e323]: |
| | | - generic [ref=f1e325] [cursor=pointer]: |
| | | - generic [ref=f1e329]: æç´¢ |
| | | - generic [ref=f1e330]: Ctrl K |
| | | - button [ref=f1e332] [cursor=pointer] |
| | | - button "light" [ref=f1e337] [cursor=pointer] |
| | | - button [ref=f1e346] [cursor=pointer] |
| | | - button [ref=f1e352] [cursor=pointer] |
| | | - button [ref=f1e355] [cursor=pointer] |
| | | - button [ref=f1e361] [cursor=pointer]: |
| | | - button [ref=f1e363] |
| | | - button "å·¥ä½å°" [ref=f1e367] [cursor=pointer] |
| | | - button "çå" [ref=f1e371] [cursor=pointer] |
| | | - generic [ref=f1e378]: |
| | | - generic [ref=f1e379]: é¦é¡µ |
| | | - generic [ref=f1e398]: |
| | | - button [ref=f1e399] [cursor=pointer] |
| | | - generic [ref=f1e406] [cursor=pointer] |
| | | - generic [ref=f1e410] [cursor=pointer] |
| | | - main [ref=f1e417]: |
| | | - generic [ref=f1e420]: |
| | | - generic [ref=f1e421]: |
| | | - generic [ref=f1e431] [cursor=pointer]: |
| | | - generic [ref=f1e432]: åç§æ»æ° |
| | | - generic [ref=f1e433]: "1" |
| | | - generic [ref=f1e444] [cursor=pointer]: |
| | | - generic [ref=f1e445]: MES åç§ |
| | | - generic [ref=f1e446]: "0" |
| | | - generic [ref=f1e457] [cursor=pointer]: |
| | | - generic [ref=f1e458]: åç§åç±» |
| | | - generic [ref=f1e459]: "1" |
| | | - generic [ref=f1e468] [cursor=pointer]: |
| | | - generic [ref=f1e469]: 计éåä½ |
| | | - generic [ref=f1e470]: "1" |
| | | - generic [ref=f1e472]: |
| | | - generic [ref=f1e480] [cursor=pointer]: |
| | | - generic [ref=f1e481]: 产线 |
| | | - generic [ref=f1e482]: "1" |
| | | - generic [ref=f1e494] [cursor=pointer]: |
| | | - generic [ref=f1e495]: çäº§æ¹æ¬¡ |
| | | - generic [ref=f1e496]: "2" |
| | | - generic [ref=f1e505] [cursor=pointer]: |
| | | - generic [ref=f1e506]: è¢ç |
| | | - generic [ref=f1e507]: "101" |
| | | - generic [ref=f1e518] [cursor=pointer]: |
| | | - generic [ref=f1e519]: æçç |
| | | - generic [ref=f1e520]: "10" |
| | | - generic [ref=f1e522]: |
| | | - generic [ref=f1e526]: |
| | | - generic [ref=f1e527]: è¢ç çæè¶å¿ |
| | | - generic [ref=f1e529]: |
| | | - generic [ref=f1e530] [cursor=pointer]: |
| | | - generic [ref=f1e531]: |
| | | - radio "è¿ 7 天" [checked] |
| | | - generic [ref=f1e532]: è¿ 7 天 |
| | | - generic [ref=f1e533] [cursor=pointer]: |
| | | - generic [ref=f1e534]: |
| | | - radio "è¿ 30 天" |
| | | - generic [ref=f1e535]: è¿ 30 天 |
| | | - generic [ref=f1e540]: æ¹æ¬¡ç¶æåå¸ |
| | | - generic [ref=f1e549]: è¢ç ç¶æåå¸ |
| | | - generic [ref=f1e558]: |
| | | - generic [ref=f1e559]: å¿«æ·å
¥å£ |
| | | - generic [ref=f1e563]: |
| | | - generic [ref=f1e564]: åç§ç®¡ç |
| | | - generic [ref=f1e572]: åç§åç±» |
| | | - generic [ref=f1e580]: æ¹æ¬¡ç产 |
| | | - generic [ref=f1e589]: èµç 管ç |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f2e7]: |
| | | - complementary [ref=f2e9]: |
| | | - generic [ref=f2e10]: |
| | | - generic [ref=f2e11] [cursor=pointer] |
| | | - link "å·¥ä¸AIæºé å¹³å° å·¥ä¸AIæºé å¹³å°" [ref=f2e16] [cursor=pointer]: |
| | | - /url: javascript:void 0 |
| | | - img "å·¥ä¸AIæºé å¹³å°" [ref=f2e19] |
| | | - generic [ref=f2e20]: å·¥ä¸AIæºé å¹³å° |
| | | - menu [ref=f2e23]: |
| | | - menuitem "é¦é¡µ" [ref=f2e24] [cursor=pointer] |
| | | - listitem [ref=f2e29]: |
| | | - generic [ref=f2e30] [cursor=pointer]: åºç¡æ°æ® |
| | | - listitem [ref=f2e38]: |
| | | - generic [ref=f2e39] [cursor=pointer]: ä»å¨ç©æµ |
| | | - listitem [ref=f2e47]: |
| | | - generic [ref=f2e48] [cursor=pointer]: ä¸è¢ä¸ç 管ç |
| | | - listitem [ref=f2e54]: |
| | | - generic [ref=f2e55] [cursor=pointer]: è´¨é管ç |
| | | - listitem [ref=f2e61]: |
| | | - generic [ref=f2e62] [cursor=pointer]: ç³»ç»ç®¡ç |
| | | - generic [ref=f2e69] [cursor=pointer] |
| | | - generic [ref=f2e74]: |
| | | - generic [ref=f2e75]: |
| | | - banner [ref=f2e76]: |
| | | - button [ref=f2e77] [cursor=pointer] |
| | | - button [ref=f2e80] [cursor=pointer] |
| | | - navigation "breadcrumb" [ref=f2e85]: |
| | | - list [ref=f2e86]: |
| | | - listitem [ref=f2e87]: |
| | | - link "é¦é¡µ" [disabled] [ref=f2e88] |
| | | - generic [ref=f2e93]: |
| | | - generic [ref=f2e95] [cursor=pointer]: |
| | | - generic [ref=f2e99]: æç´¢ |
| | | - generic [ref=f2e100]: Ctrl K |
| | | - button [ref=f2e102] [cursor=pointer] |
| | | - button "dark" [active] [ref=f2e107] [cursor=pointer] |
| | | - button [ref=f2e116] [cursor=pointer] |
| | | - button [ref=f2e122] [cursor=pointer] |
| | | - button [ref=f2e125] [cursor=pointer] |
| | | - button [ref=f2e131] [cursor=pointer]: |
| | | - button [ref=f2e133] |
| | | - button "å·¥ä½å°" [ref=f2e137] [cursor=pointer] |
| | | - button "çå" [ref=f2e141] [cursor=pointer] |
| | | - generic [ref=f2e148]: |
| | | - generic [ref=f2e149]: é¦é¡µ |
| | | - generic [ref=f2e168]: |
| | | - button [ref=f2e169] [cursor=pointer] |
| | | - generic [ref=f2e176] [cursor=pointer] |
| | | - generic [ref=f2e180] [cursor=pointer] |
| | | - main [ref=f2e187]: |
| | | - generic [ref=f2e190]: |
| | | - generic [ref=f2e191]: |
| | | - generic [ref=f2e201] [cursor=pointer]: |
| | | - generic [ref=f2e202]: åç§æ»æ° |
| | | - generic [ref=f2e203]: "1" |
| | | - generic [ref=f2e214] [cursor=pointer]: |
| | | - generic [ref=f2e215]: MES åç§ |
| | | - generic [ref=f2e216]: "0" |
| | | - generic [ref=f2e227] [cursor=pointer]: |
| | | - generic [ref=f2e228]: åç§åç±» |
| | | - generic [ref=f2e229]: "1" |
| | | - generic [ref=f2e238] [cursor=pointer]: |
| | | - generic [ref=f2e239]: 计éåä½ |
| | | - generic [ref=f2e240]: "1" |
| | | - generic [ref=f2e242]: |
| | | - generic [ref=f2e250] [cursor=pointer]: |
| | | - generic [ref=f2e251]: 产线 |
| | | - generic [ref=f2e252]: "1" |
| | | - generic [ref=f2e264] [cursor=pointer]: |
| | | - generic [ref=f2e265]: çäº§æ¹æ¬¡ |
| | | - generic [ref=f2e266]: "2" |
| | | - generic [ref=f2e275] [cursor=pointer]: |
| | | - generic [ref=f2e276]: è¢ç |
| | | - generic [ref=f2e277]: "101" |
| | | - generic [ref=f2e288] [cursor=pointer]: |
| | | - generic [ref=f2e289]: æçç |
| | | - generic [ref=f2e290]: "10" |
| | | - generic [ref=f2e292]: |
| | | - generic [ref=f2e296]: |
| | | - generic [ref=f2e297]: è¢ç çæè¶å¿ |
| | | - generic [ref=f2e299]: |
| | | - generic [ref=f2e300] [cursor=pointer]: |
| | | - generic [ref=f2e301]: |
| | | - radio "è¿ 7 天" [checked] |
| | | - generic [ref=f2e302]: è¿ 7 天 |
| | | - generic [ref=f2e303] [cursor=pointer]: |
| | | - generic [ref=f2e304]: |
| | | - radio "è¿ 30 天" |
| | | - generic [ref=f2e305]: è¿ 30 天 |
| | | - generic [ref=f2e310]: æ¹æ¬¡ç¶æåå¸ |
| | | - generic [ref=f2e319]: è¢ç ç¶æåå¸ |
| | | - generic [ref=f2e328]: |
| | | - generic [ref=f2e329]: å¿«æ·å
¥å£ |
| | | - generic [ref=f2e333]: |
| | | - generic [ref=f2e334]: åç§ç®¡ç |
| | | - generic [ref=f2e342]: åç§åç±» |
| | | - generic [ref=f2e350]: æ¹æ¬¡ç产 |
| | | - generic [ref=f2e359]: èµç 管ç |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f5e4]: |
| | | - generic [ref=f5e5]: |
| | | - generic [ref=f5e6]: |
| | | - generic [ref=f5e7]: |
| | | - generic: |
| | | - button [ref=f5e8] [cursor=pointer] |
| | | - button [ref=f5e12] [cursor=pointer] |
| | | - button [ref=f5e14] [cursor=pointer] |
| | | - button [ref=f5e16] [cursor=pointer] |
| | | - button [ref=f5e18] [cursor=pointer] |
| | | - button [ref=f5e20] [cursor=pointer] |
| | | - button [ref=f5e22] [cursor=pointer] |
| | | - button [ref=f5e24] [cursor=pointer] |
| | | - button [ref=f5e31] [cursor=pointer] |
| | | - button [ref=f5e35] [cursor=pointer] |
| | | - button "dark" [ref=f5e41] [cursor=pointer] |
| | | - generic [ref=f5e50]: |
| | | - generic [ref=f5e79]: |
| | | - generic [ref=f5e88]: |
| | | - generic [ref=f5e89]: æ´ |
| | | - strong [ref=f5e90]: 26.8°C |
| | | - generic [ref=f5e94]: |
| | | - generic [ref=f5e95]: 湿度 |
| | | - strong [ref=f5e96]: 68% |
| | | - generic [ref=f5e104]: |
| | | - generic [ref=f5e105]: é鍿¦ç |
| | | - strong [ref=f5e106]: 20% |
| | | - generic [ref=f5e111]: |
| | | - generic [ref=f5e112]: å±±ä¸ç |
| | | - strong [ref=f5e113]: æµåå¸ |
| | | - generic [ref=f5e114]: |
| | | - generic [ref=f5e115]: |
| | | - generic [ref=f5e125]: |
| | | - generic [ref=f5e126]: ç§æ¤ä¸æ°ååå¹³å° |
| | | - generic [ref=f5e127]: AGRICULTURE DIGITAL PLATFORM |
| | | - generic [ref=f5e128]: æ°åèµè½åä¸ Â· ç§æå¼é¢æªæ¥ |
| | | - generic [ref=f5e132]: |
| | | - generic "å¹³å°è¿è¡æ¦è§" [ref=f5e133]: |
| | | - generic [ref=f5e139]: |
| | | - text: ç§æ¤é¢ç§¯ |
| | | - generic [ref=f5e140]: 12,580亩 |
| | | - generic [ref=f5e141]: è¾æ¨æ¥ â 2.35% |
| | | - generic [ref=f5e148]: |
| | | - text: å¨çº¿è®¾å¤ |
| | | - generic [ref=f5e149]: 1,286å° |
| | | - generic [ref=f5e150]: è¾æ¨æ¥ â 5.21% |
| | | - generic [ref=f5e156]: |
| | | - text: 仿¥çæº |
| | | - generic [ref=f5e157]: 328亩 |
| | | - generic [ref=f5e158]: è¾æ¨æ¥ â 1.15% |
| | | - generic [ref=f5e164]: |
| | | - text: AI é¢è¦ |
| | | - generic [ref=f5e165]: 6æ¡ |
| | | - generic [ref=f5e166]: è¾æ¨æ¥ â 12.50% |
| | | - generic [ref=f5e167]: |
| | | - generic [ref=f5e168]: |
| | | - generic [ref=f5e169]: å壤墿
çæµ |
| | | - generic [ref=f5e170]: |
| | | - strong [ref=f5e173]: 68.5% |
| | | - generic [ref=f5e174]: å壤湿度 |
| | | - img [ref=f5e175]: |
| | | - generic [ref=f5e177]: |
| | | - generic [ref=f5e178]: 100% |
| | | - generic [ref=f5e179]: 50% |
| | | - generic [ref=f5e180]: 0% |
| | | - generic [ref=f5e183]: |
| | | - generic [ref=f5e184]: 00:00 |
| | | - generic [ref=f5e185]: 06:00 |
| | | - generic [ref=f5e186]: 12:00 |
| | | - generic [ref=f5e187]: 18:00 |
| | | - generic [ref=f5e188]: 24:00 |
| | | - generic [ref=f5e189]: |
| | | - generic [ref=f5e190]: AI æºè½åæ |
| | | - paragraph [ref=f5e194]: å½åä½ç©é¿å¿è¯å¥½ï¼å壤墿
éå®ï¼æªæ¥3å¤©æ ææ¾éé¨ï¼å»ºè®®éæ¶çæºï¼ä¿è¯ä½ç©ç¨³äº§é«äº§ã |
| | | - generic [ref=f5e195]: |
| | | - generic [ref=f5e196]: © 2026 ç§æ¤ä¸æ°ååå¹³å° çæææ |
| | | - generic [ref=f5e197]: é²ICPå¤2026001234å·-1 |
| | | - generic [ref=f5e198] [cursor=pointer]: éç§æ¿ç |
| | | - generic [ref=f5e199]: "|" |
| | | - generic [ref=f5e200] [cursor=pointer]: ç¨æ·åè®® |
| | | - generic [ref=f5e204]: |
| | | - generic [ref=f5e205]: |
| | | - heading "欢è¿åæ¥" [level=2] [ref=f5e206] |
| | | - paragraph [ref=f5e207]: |
| | | - generic [ref=f5e208]: ç»å½ç§æ¤ä¸æ°ååå¹³å°ï¼å¼å¯æºæ
§ç§æ¤ |
| | | - generic [ref=f5e210]: |
| | | - textbox "请è¾å
¥ç¨æ·å" [ref=f5e216]: admin |
| | | - generic [ref=f5e222]: |
| | | - textbox "请è¾å
¥å¯ç " [ref=f5e223]: admin123 |
| | | - generic [ref=f5e224] [cursor=pointer] |
| | | - generic [ref=f5e232]: |
| | | - checkbox "è®°ä½è´¦å·" [ref=f5e233] [cursor=pointer] |
| | | - generic [ref=f5e234] [cursor=pointer]: è®°ä½è´¦å· |
| | | - button "login" [ref=f5e235] [cursor=pointer]: ç»å½ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [active]: å·¥ä¸AIæºé å¹³å° |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | - generic [ref=f16e4]: |
| | | - generic [ref=f16e5]: |
| | | - generic [ref=f16e6]: |
| | | - generic [ref=f16e7]: |
| | | - generic: |
| | | - button [ref=f16e8] [cursor=pointer] |
| | | - button [ref=f16e12] [cursor=pointer] |
| | | - button [ref=f16e14] [cursor=pointer] |
| | | - button [ref=f16e16] [cursor=pointer] |
| | | - button [ref=f16e18] [cursor=pointer] |
| | | - button [ref=f16e20] [cursor=pointer] |
| | | - button [ref=f16e22] [cursor=pointer] |
| | | - button [ref=f16e24] [cursor=pointer] |
| | | - button [ref=f16e31] [cursor=pointer] |
| | | - button [ref=f16e35] [cursor=pointer] |
| | | - button "dark" [ref=f16e41] [cursor=pointer] |
| | | - generic [ref=f16e51]: |
| | | - generic [ref=f16e52]: |
| | | - generic [ref=f16e62]: |
| | | - generic [ref=f16e63]: ç§æ¤ä¸æ°ååå¹³å° |
| | | - generic [ref=f16e64]: AGRICULTURE DIGITAL PLATFORM |
| | | - generic [ref=f16e65]: æ°åèµè½åä¸ Â· ç§æå¼é¢æªæ¥ |
| | | - generic [ref=f16e69]: |
| | | - generic "å¹³å°è¿è¡æ¦è§" [ref=f16e70]: |
| | | - generic [ref=f16e76]: |
| | | - text: ç§æ¤é¢ç§¯ |
| | | - generic [ref=f16e77]: 12,580亩 |
| | | - generic [ref=f16e78]: è¾æ¨æ¥ â 2.35% |
| | | - generic [ref=f16e85]: |
| | | - text: å¨çº¿è®¾å¤ |
| | | - generic [ref=f16e86]: 1,286å° |
| | | - generic [ref=f16e87]: è¾æ¨æ¥ â 5.21% |
| | | - generic [ref=f16e93]: |
| | | - text: 仿¥çæº |
| | | - generic [ref=f16e94]: 328亩 |
| | | - generic [ref=f16e95]: è¾æ¨æ¥ â 1.15% |
| | | - generic [ref=f16e101]: |
| | | - text: AI é¢è¦ |
| | | - generic [ref=f16e102]: 6æ¡ |
| | | - generic [ref=f16e103]: è¾æ¨æ¥ â 12.50% |
| | | - generic [ref=f16e104]: |
| | | - generic [ref=f16e105]: |
| | | - generic [ref=f16e106]: å壤墿
çæµ |
| | | - generic [ref=f16e107]: |
| | | - strong [ref=f16e110]: 68.5% |
| | | - generic [ref=f16e111]: å壤湿度 |
| | | - img [ref=f16e112]: |
| | | - generic [ref=f16e114]: |
| | | - generic [ref=f16e115]: 100% |
| | | - generic [ref=f16e116]: 50% |
| | | - generic [ref=f16e117]: 0% |
| | | - generic [ref=f16e120]: |
| | | - generic [ref=f16e121]: 00:00 |
| | | - generic [ref=f16e122]: 06:00 |
| | | - generic [ref=f16e123]: 12:00 |
| | | - generic [ref=f16e124]: 18:00 |
| | | - generic [ref=f16e125]: 24:00 |
| | | - generic [ref=f16e126]: |
| | | - generic [ref=f16e127]: AI æºè½åæ |
| | | - paragraph [ref=f16e131]: å½åä½ç©é¿å¿è¯å¥½ï¼å壤墿
éå®ï¼æªæ¥3å¤©æ ææ¾éé¨ï¼å»ºè®®éæ¶çæºï¼ä¿è¯ä½ç©ç¨³äº§é«äº§ã |
| | | - generic [ref=f16e135]: |
| | | - generic [ref=f16e136]: |
| | | - heading "欢è¿åæ¥" [level=2] [ref=f16e137] |
| | | - paragraph [ref=f16e138]: |
| | | - generic [ref=f16e139]: ç»å½ç§æ¤ä¸æ°ååå¹³å°ï¼å¼å¯æºæ
§ç§æ¤ |
| | | - generic [ref=f16e141]: |
| | | - textbox "è´¦å·" [ref=f16e147]: |
| | | - /placeholder: 请è¾å
¥ç¨æ·å |
| | | - text: admin |
| | | - generic [ref=f16e153]: |
| | | - textbox "å¯ç " [ref=f16e154]: |
| | | - /placeholder: 请è¾å
¥å¯ç |
| | | - text: admin123 |
| | | - button "忢å¯ç å¯è§æ§" [ref=f16e155] [cursor=pointer] |
| | | - generic [ref=f16e163]: |
| | | - checkbox "è®°ä½è´¦å·" [ref=f16e164] [cursor=pointer] |
| | | - generic [ref=f16e165] [cursor=pointer]: è®°ä½è´¦å· |
| | | - button "login" [ref=f16e166] [cursor=pointer]: ç»å½ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # MES éå®åºåºæ«ç æ£è´§ - å端èè°æ¹æ¡ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - éå®åºåºå详æ
页 |
| | | - éå®åºåºæ£è´§é¡µ |
| | | - åºåå°è´¦æ¥è¯¢é¡µ |
| | | |
| | | ## ä¸å¡æµç¨ä¸æ°æ®å¸¦å
¥ |
| | | |
| | | 1. éå®åºåºåè¿å
¥âå¾
æ£è´§âç¶æåï¼åç«¯æ«æè¢ç ææçç ã |
| | | 2. æ«æå
容è°ç¨æ«ç æ¥å£ï¼å端è¯å«ç ç±»åå¹¶å
³èçäº§æ¹æ¬¡ãç©æååºåè®°å½ã |
| | | 3. æ«ç ç»æä¸çåºåè®°å½ãæ¹æ¬¡ãä»åºãåºåºãåºä½åæ°é带å
¥éå®åºåºæç»ã |
| | | 4. æ«æå®æåç»§ç»è°ç¨åæâæ§è¡æ£è´§âæ¥å£ï¼ç»ä¸å建åºåå ç¨ï¼æ«ç æ¥å£ä¸ç´æ¥æ£ååºåã |
| | | 5. åºåºå宿æ¶ç±åæâæ§è¡åºåºâæ¥å£æ£ååºåï¼å¹¶æ´æ°åºåç¶æã |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/mes/wm/product-sales/scan` | æ«æè¢ç ææçç å¹¶çæéå®åºåºæç» | |
| | | | PUT | `/mes/wm/product-sales/stock?id={id}` | æ§è¡æ£è´§å¹¶å建åºåå ç¨ | |
| | | | PUT | `/mes/wm/product-sales/finish?id={id}` | 宿åºåºå¹¶æ£ååºå | |
| | | |
| | | **æ«ç 请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | salesId | Long | æ¯ | éå®åºåºå IDï¼åæ®å¿
é¡»å¤äºå¾
æ£è´§ç¶æ | |
| | | | scanContent | String | æ¯ | è¢ç ææçç | |
| | | | quantity | BigDecimal | å¦ | æ¬æ¬¡æ£è´§æ°éï¼ä¸å¡«æ¶ä½¿ç¨éå®è¡æ°é | |
| | | |
| | | **æ«ç ååºå段ï¼** |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | scanType | String | `BAG` è¢ç ï¼`PALLET` æçç | |
| | | | codeId | Long | ç è®°å½ ID | |
| | | | itemIdãbatchIdãbatchCode | Long/Long/String | ç©æåæ¹æ¬¡ä¿¡æ¯ | |
| | | | materialStockId | Long | å
³èåºåè®°å½ ID | |
| | | | availableQuantity | BigDecimal | å½ååºåæ°é | |
| | | | scanQuantityãoutboundQuantity | BigDecimal | æ¬æ¬¡æ«ææ°éååºåºæ°é | |
| | | | detailId | Long | çæçéå®åºåºæç» ID | |
| | | | warehouseIdãlocationIdãareaId | Long | åºåæå¨ä»åºãåºåºãåºä½ | |
| | | | alreadyScanned | Boolean | é夿«ææ¶ä¸º trueï¼å¹¶è¿åå·²ææç» ID | |
| | | | palletExpanded | Boolean | æçå±å¼æ è¯ | |
| | | | bagCountãinboundBagCount | Integer | æçè¢ç æ»æ°ã已累计è¢ç æ° | |
| | | | message | String | æä½æç¤º | |
| | | |
| | | ## åæ®µå±ç¤ºè§å |
| | | |
| | | | åæ®µ | å±ç¤ºä½ç½® | 说æ | |
| | | |------|----------|------| |
| | | | scanTypeãscanContent | æ«ç ç»æåº | æ¾ç¤ºè¯å«ç±»åååå§ç å¼ | |
| | | | itemCodeãitemNameãbatchCode | æç»è¡¨ | 仿«ç ç»æå¸¦å
¥ï¼ä¸å
许å端èªè¡æ¹å | |
| | | | materialStockIdãä»åºãåºåºãåºä½ | æç»æ°æ® | ä¿ååºåå
³èï¼ç¨äºæ£è´§ååºåºæ ¡éª | |
| | | | availableQuantity | æ«ç ç»æåº | ç¨äºæç¤ºå½ååºåæ°é | |
| | | | stockState | åºåå°è´¦ | `10` æååºã`20` åæ ¼åºã`30` å·²åºåº | |
| | | |
| | | ## ä¸å¡è§å说æ |
| | | |
| | | | åºæ¯ | è§å | |
| | | |------|------| |
| | | | è¢ç æ«æ | æè¢ç å
³èæ¹æ¬¡åç©æï¼å¹¶çæå¸¦ `bagCodeId` çæç» | |
| | | | æçæ«æ | å
³èæçåå
¶è¢ç ï¼çæå¸¦ `palletCodeId` çæç»ï¼å¹¶è¿åå±å¼ç»è®¡ | |
| | | | é夿«æ | åä¸éå®åºåºåé夿«æåä¸ç æ¶ä¸éå¤çææç»ï¼è¿åå·²ææç» | |
| | | | æ°éè¶
é | æ«ææ°éä¸å¾è¶
è¿åºåå¯ç¨æ°éï¼ä¹ä¸å¾è¶
è¿éå®è¡å©ä½æ°é | |
| | | | åºååæ´ | æ«ç åªçææç»ï¼æ£è´§æ¶å ç¨ï¼å®æåºåºæ¶æ£ååºå | |
| | | | åºåç¶æ | æ°å»ºåºå为æååºï¼å
¥åºåææ°éä¸ºåæ ¼åºï¼æ°éæ£åè³é¶ä¸ºå·²åºåº | |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - æ«ç æ¥å£åªè½ç¨äºå¾
æ£è´§ç¶æçéå®åºåºåã |
| | | - æçå
è¢ç å±å¼çå
·ä½æç»æ°éåºä»¥æ¥å£è¿åç `bagCount` å `inboundBagCount` 为åã |
| | | - é夿«ç ååºçé¨åç©æååºååæ®µå¯è½ä¸ºç©ºï¼å端åºä¼å
ä½¿ç¨ `detailId` æ¥è¯¢å·²ææç»ã |
| | | - å端æ¥å£åæ´ä¸ä¿®æ¹ `mom-pro2-before` å端项ç®ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- åºåºæµé管çï¼éå®åºåºä¸è¢ç /æçç å
³èï¼æ ç§æ·åæ®µï¼ |
| | | -- æ§è¡åè¯·ç¡®è®¤ç®æ æ°æ®åºä¸º mom-thzyï¼å¹¶éæ¡æ§è¡ã |
| | | |
| | | ALTER TABLE mes_wm_product_sales_detail |
| | | ADD COLUMN bag_code_id bigint DEFAULT NULL COMMENT 'è¢ç ç¼å·' AFTER area_id; |
| | | ALTER TABLE mes_wm_product_sales_detail |
| | | ADD COLUMN pallet_code_id bigint DEFAULT NULL COMMENT 'æçç ç¼å·' AFTER bag_code_id; |
| | | ALTER TABLE mes_wm_product_sales_detail |
| | | ADD INDEX idx_sales_detail_bag_code (bag_code_id); |
| | | ALTER TABLE mes_wm_product_sales_detail |
| | | ADD INDEX idx_sales_detail_pallet_code (pallet_code_id); |
| | | |
| | | ALTER TABLE mes_pro_bag_code |
| | | ADD COLUMN sales_id bigint DEFAULT NULL COMMENT 'æè¿éå®åºåºåç¼å·' AFTER inbound_line_code; |
| | | ALTER TABLE mes_pro_bag_code |
| | | ADD COLUMN outbound_time datetime DEFAULT NULL COMMENT 'æè¿éå®åºåºæ¶é´' AFTER sales_id; |
| | | ALTER TABLE mes_pro_bag_code |
| | | ADD INDEX idx_bag_code_sales (sales_id); |
| | | |
| | | ALTER TABLE mes_pro_pallet |
| | | ADD COLUMN sales_id bigint DEFAULT NULL COMMENT 'æè¿éå®åºåºåç¼å·' AFTER status; |
| | | ALTER TABLE mes_pro_pallet |
| | | ADD COLUMN outbound_time datetime DEFAULT NULL COMMENT 'æè¿éå®åºåºæ¶é´' AFTER sales_id; |
| | | ALTER TABLE mes_pro_pallet |
| | | ADD INDEX idx_pallet_sales (sales_id); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ä»å¨åºåç¶æåå§åï¼æ ç§æ·åæ®µï¼ |
| | | SET @stock_state_exists = ( |
| | | SELECT COUNT(*) |
| | | FROM information_schema.columns |
| | | WHERE table_schema = DATABASE() |
| | | AND table_name = 'mes_wm_material_stock' |
| | | AND column_name = 'stock_state' |
| | | ); |
| | | SET @stock_state_sql = IF( |
| | | @stock_state_exists = 0, |
| | | 'ALTER TABLE mes_wm_material_stock ADD COLUMN stock_state tinyint NOT NULL DEFAULT 20 COMMENT ''åºåç¶æï¼10æååºï¼20åæ ¼åºï¼30å·²åºåº'' AFTER in_transit_quantity', |
| | | 'SELECT 1' |
| | | ); |
| | | PREPARE stock_state_stmt FROM @stock_state_sql; |
| | | EXECUTE stock_state_stmt; |
| | | DEALLOCATE PREPARE stock_state_stmt; |
| | | |
| | | SET @stock_state_index_exists = ( |
| | | SELECT COUNT(*) |
| | | FROM information_schema.statistics |
| | | WHERE table_schema = DATABASE() |
| | | AND table_name = 'mes_wm_material_stock' |
| | | AND index_name = 'idx_stock_state_query' |
| | | ); |
| | | SET @stock_state_index_sql = IF( |
| | | @stock_state_index_exists = 0, |
| | | 'CREATE INDEX idx_stock_state_query ON mes_wm_material_stock (stock_state, item_id, batch_id, warehouse_id, receipt_time)', |
| | | 'SELECT 1' |
| | | ); |
| | | PREPARE stock_state_index_stmt FROM @stock_state_index_sql; |
| | | EXECUTE stock_state_index_stmt; |
| | | DEALLOCATE PREPARE stock_state_index_stmt; |
| | |
| | | @Schema(description = "ä¾åºåç¼å·") |
| | | private Long vendorId; |
| | | |
| | | @Schema(description = "åºåç¶æï¼10-æååºï¼20-åæ ¼åºï¼30-å·²åºåº") |
| | | private Integer stockState; |
| | | |
| | | @Schema(description = "å¼å§æ¶é´ï¼å¨æçç¹ç¨ï¼") |
| | | private LocalDateTime startTime; |
| | | |
| | |
| | | @Schema(description = "ä¾åºåç¼å·", example = "1") |
| | | private Long vendorId; |
| | | |
| | | @Schema(description = "åºåç¶æï¼10-æååºï¼20-åæ ¼åºï¼30-å·²åºåº", example = "20") |
| | | private Integer stockState; |
| | | |
| | | @Schema(description = "æ¯å¦å»ç»", example = "false") |
| | | private Boolean frozen; |
| | | |
| | |
| | | @ExcelProperty("å
¥åºæ¶é´") |
| | | private LocalDateTime receiptTime; |
| | | |
| | | @Schema(description = "åºåç¶æï¼10-æååºï¼20-åæ ¼åºï¼30-å·²åºåº", example = "20") |
| | | @ExcelProperty("åºåç¶æ") |
| | | private Integer stockState; |
| | | |
| | | @Schema(description = "æ¯å¦å»ç»", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") |
| | | @ExcelProperty("æ¯å¦å»ç»") |
| | | private Boolean frozen; |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanRespVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; |
| | | import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; |
| | |
| | | return success(productSalesService.checkProductSalesQuantity(id)); |
| | | } |
| | | |
| | | @PostMapping("/scan") |
| | | @Operation(summary = "æ«ç æ£è´§") |
| | | @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:stock')") |
| | | public CommonResult<MesWmProductSalesScanRespVO> scanProductSales( |
| | | @Valid @RequestBody MesWmProductSalesScanReqVO reqVO) { |
| | | return success(productSalesService.scanProductSales(reqVO)); |
| | | } |
| | | |
| | | @PutMapping("/stock") |
| | | @Operation(summary = "æ§è¡æ£è´§") |
| | | @Parameter(name = "id", description = "ç¼å·", required = true) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Schema(description = "管çåå° - MES éå®åºåºæ«ç æ£è´§ Request VO") |
| | | @Data |
| | | public class MesWmProductSalesScanReqVO { |
| | | |
| | | @Schema(description = "éå®åºåºåID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| | | @NotNull(message = "éå®åºåºåIDä¸è½ä¸ºç©º") |
| | | private Long salesId; |
| | | |
| | | @Schema(description = "æ«æå
容ï¼è¢ç ææçç ï¼", requiredMode = Schema.RequiredMode.REQUIRED, example = "PC2026081920-0001") |
| | | @NotEmpty(message = "æ«æå
容ä¸è½ä¸ºç©º") |
| | | private String scanContent; |
| | | |
| | | @Schema(description = "æ¬æ¬¡åºåºæ°éï¼ä¸ºç©ºåå该è¢ç /æ´æå
¨é¨æ°éï¼", example = "50") |
| | | private BigDecimal quantity; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Schema(description = "管çåå° - MES éå®åºåºæ«ç æ£è´§ Response VO") |
| | | @Data |
| | | public class MesWmProductSalesScanRespVO { |
| | | |
| | | @Schema(description = "è¯å«ç±»åï¼PALLET-æçç ï¼BAG-è¢ç ", example = "BAG") |
| | | private String scanType; |
| | | |
| | | @Schema(description = "æ«æçç ç¼å·", example = "12") |
| | | private Long codeId; |
| | | |
| | | @Schema(description = "æ«æå
容ï¼è¢ç ææçç ï¼", example = "PC2026081920-0001") |
| | | private String scanContent; |
| | | |
| | | @Schema(description = "ç©æID", example = "1") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "ç©æç¼ç ", example = "ITEM001") |
| | | private String itemCode; |
| | | |
| | | @Schema(description = "ç©æåç§°", example = "稻ç§") |
| | | private String itemName; |
| | | |
| | | @Schema(description = "æ¹æ¬¡ID", example = "1") |
| | | private Long batchId; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·", example = "PC2026081920") |
| | | private String batchCode; |
| | | |
| | | @Schema(description = "åºåè®°å½ID", example = "1") |
| | | private Long materialStockId; |
| | | |
| | | @Schema(description = "å¯åºåºæ°é", example = "50.00") |
| | | private BigDecimal availableQuantity; |
| | | |
| | | @Schema(description = "æ¬è¢/æ¬æå®é
æ°é", example = "50.00") |
| | | private BigDecimal scanQuantity; |
| | | |
| | | @Schema(description = "æ¬æ¬¡åºåºæ°é", example = "50.00") |
| | | private BigDecimal outboundQuantity; |
| | | |
| | | @Schema(description = "æ¯å¦å·²æ«æè¿ï¼å¹çè¿åå·²ææç»ï¼", example = "false") |
| | | private Boolean alreadyScanned; |
| | | |
| | | @Schema(description = "çæçéå®åºåºæç»IDï¼å¹çè¿åæ¶äº¦æå¼ï¼", example = "100") |
| | | private Long detailId; |
| | | |
| | | @Schema(description = "ä»åºID", example = "1") |
| | | private Long warehouseId; |
| | | |
| | | @Schema(description = "åºåºID", example = "1") |
| | | private Long locationId; |
| | | |
| | | @Schema(description = "åºä½ID", example = "1") |
| | | private Long areaId; |
| | | |
| | | @Schema(description = "æ¯å¦æçå±å¼ï¼æçç å¿
为 trueï¼", example = "false") |
| | | private Boolean palletExpanded; |
| | | |
| | | @Schema(description = "ç»å®çè¢ç æ°éï¼æçå±å¼æ¶è¿åï¼", example = "100") |
| | | private Integer bagCount; |
| | | |
| | | @Schema(description = "已累å åºåºçè¢ç æ°éï¼æçå±å¼æ¶è¿åï¼", example = "0") |
| | | private Integer inboundBagCount; |
| | | |
| | | @Schema(description = "æä½ä¿¡æ¯æç¤º", example = "æ«ç æå") |
| | | private String message; |
| | | |
| | | } |
| | |
| | | private Long inboundEventId; |
| | | private String inboundDeviceCode; |
| | | private String inboundLineCode; |
| | | private Long salesId; |
| | | private LocalDateTime outboundTime; |
| | | private String remark; |
| | | } |
| | |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * æè¿éå®åºåºåç¼å· |
| | | */ |
| | | private Long salesId; |
| | | /** |
| | | * æè¿éå®åºåºæ¶é´ |
| | | */ |
| | | private java.time.LocalDateTime outboundTime; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | // ==================== ç¶æ ==================== |
| | | |
| | | /** |
| | | * åºåç¶æï¼10-æååºï¼20-åæ ¼åºï¼30-å·²åºåº |
| | | */ |
| | | private Integer stockState; |
| | | |
| | | /** |
| | | * æ¯å¦å»ç» |
| | | */ |
| | | private Boolean frozen; |
| | |
| | | */ |
| | | private Long areaId; |
| | | /** |
| | | * è¢ç ç¼å· |
| | | */ |
| | | private Long bagCodeId; |
| | | /** |
| | | * æçç ç¼å· |
| | | */ |
| | | private Long palletCodeId; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | @Param("toStatus") Integer toStatus, @Param("cancelTime") LocalDateTime cancelTime, |
| | | @Param("cancelReason") String cancelReason); |
| | | |
| | | @Update("UPDATE mes_pro_bag_code SET sales_id = #{salesId}, outbound_time = #{outboundTime}, update_time = NOW() " |
| | | + "WHERE id = #{id} AND deleted = 0") |
| | | void markOutbound(@Param("id") Long id, @Param("salesId") Long salesId, |
| | | @Param("outboundTime") LocalDateTime outboundTime); |
| | | |
| | | @Update("UPDATE mes_pro_bag_code SET sales_id = NULL, outbound_time = NULL, update_time = NOW() " |
| | | + "WHERE id = #{id} AND deleted = 0") |
| | | void clearOutbound(@Param("id") Long id); |
| | | |
| | | @Select("SELECT COUNT(*) FROM mes_pro_bag_code WHERE batch_id = #{batchId} " + |
| | | "AND deleted = 0 AND status <> 30") |
| | | int selectEffectiveCountByBatchId(@Param("batchId") Long batchId); |
| | |
| | | @Select("SELECT IFNULL(MAX(pallet_no), 0) FROM mes_pro_pallet WHERE batch_id = #{batchId}") |
| | | Integer selectMaxPalletNo(@Param("batchId") Long batchId); |
| | | |
| | | @org.apache.ibatis.annotations.Update("UPDATE mes_pro_pallet SET sales_id = #{salesId}, outbound_time = #{outboundTime}, update_time = NOW() " |
| | | + "WHERE id = #{id} AND deleted = 0") |
| | | void markOutbound(@Param("id") Long id, @Param("salesId") Long salesId, |
| | | @Param("outboundTime") java.time.LocalDateTime outboundTime); |
| | | |
| | | @org.apache.ibatis.annotations.Update("UPDATE mes_pro_pallet SET sales_id = NULL, outbound_time = NULL, update_time = NOW() " |
| | | + "WHERE id = #{id} AND deleted = 0") |
| | | void clearOutbound(@Param("id") Long id); |
| | | |
| | | } |
| | |
| | | .eqIfPresent(MesWmMaterialStockDO::getLocationId, reqVO.getLocationId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getAreaId, reqVO.getAreaId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getVendorId, reqVO.getVendorId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getStockState, reqVO.getStockState()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getFrozen, reqVO.getFrozen()); |
| | | wrapper.ne(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) |
| | | .orderByAsc(MesWmMaterialStockDO::getReceiptTime); |
| | |
| | | .eqIfPresent(MesWmMaterialStockDO::getItemId, reqVO.getItemId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getBatchId, reqVO.getBatchId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getVendorId, reqVO.getVendorId()) |
| | | .eqIfPresent(MesWmMaterialStockDO::getStockState, reqVO.getStockState()) |
| | | .likeIfPresent(MesWmMaterialStockDO::getBatchCode, reqVO.getBatchCode()) |
| | | .geIfPresent(MesWmMaterialStockDO::getUpdateTime, reqVO.getStartTime()) |
| | | .leIfPresent(MesWmMaterialStockDO::getUpdateTime, reqVO.getEndTime()) |
| | |
| | | /** |
| | | * æç©æç¼å·æ¹éæ¥è¯¢åºåè®°å½ï¼ç¨äºç©æéæ±åºåæ ¡éªï¼ |
| | | */ |
| | | default List<MesWmMaterialStockDO> selectListByItemAndBatch(Long itemId, Long batchId) { |
| | | return selectList(new LambdaQueryWrapperX<MesWmMaterialStockDO>() |
| | | .eq(MesWmMaterialStockDO::getItemId, itemId) |
| | | .eqIfPresent(MesWmMaterialStockDO::getBatchId, batchId) |
| | | .gt(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) |
| | | .orderByAsc(MesWmMaterialStockDO::getReceiptTime)); |
| | | } |
| | | |
| | | default List<MesWmMaterialStockDO> selectListByItemIds(Collection<Long> itemIds) { |
| | | if (itemIds == null || itemIds.isEmpty()) { |
| | | return java.util.Collections.emptyList(); |
| | |
| | | return selectList(MesWmProductSalesDetailDO::getSalesId, salesId); |
| | | } |
| | | |
| | | default MesWmProductSalesDetailDO selectBySalesIdAndBagCodeId(Long salesId, Long bagCodeId) { |
| | | return selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MesWmProductSalesDetailDO>() |
| | | .eq(MesWmProductSalesDetailDO::getSalesId, salesId) |
| | | .eq(MesWmProductSalesDetailDO::getBagCodeId, bagCodeId)); |
| | | } |
| | | |
| | | default MesWmProductSalesDetailDO selectBySalesIdAndPalletCodeId(Long salesId, Long palletCodeId) { |
| | | return selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MesWmProductSalesDetailDO>() |
| | | .eq(MesWmProductSalesDetailDO::getSalesId, salesId) |
| | | .eq(MesWmProductSalesDetailDO::getPalletCodeId, palletCodeId)); |
| | | } |
| | | |
| | | default void deleteByLineId(Long lineId) { |
| | | delete(MesWmProductSalesDetailDO::getLineId, lineId); |
| | | } |
| | |
| | | ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH = new ErrorCode(1_040_714_033, |
| | | "åºåºè¡ OQC æ£éªæ è¯ä¸åè´§éç¥åè¡ä¸ä¸è´"); |
| | | |
| | | // ========== MES éå®åºåº-æ«ç æ£è´§ï¼1-040-714-100ï¼ ========== |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_BAG_NOT_EXISTS = new ErrorCode(1_040_714_100, "æ«æçè¢ç ä¸å卿已ä½åº"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_PALLET_NOT_EXISTS = new ErrorCode(1_040_714_101, "æ«æçæçç ä¸å卿已ä½åº"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_PALLET_NOT_BOUND = new ErrorCode(1_040_714_102, "æ«æçæçç æªç»å®ä»»ä½è¢ç ï¼æ æ³åºåº"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_BAG_NOT_INBOUND = new ErrorCode(1_040_714_103, "è¢ç å°æªå
¥åºï¼æ æ³åºåº"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_BAG_NO_BATCH = new ErrorCode(1_040_714_104, "è¢ç æ å
³èçäº§æ¹æ¬¡ï¼æ æ³åºåº"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_STOCK_NOT_FOUND = new ErrorCode(1_040_714_105, "æ«ææ¹æ¬¡å¨åæ ¼åºä¸æªæ¾å°å¯¹åºåºåè®°å½"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_NO_MATCH_LINE = new ErrorCode(1_040_714_106, "åºåºå䏿²¡æä¸è¯¥ç©æ/æ¹æ¬¡å¹é
çè¡"); |
| | | ErrorCode WM_PRODUCT_SALES_SCAN_BAG_ALREADY_SCANNED = new ErrorCode(1_040_714_107, "该è¢ç å·²æ«æåºåºï¼è¯·å¿é夿«æ"); |
| | | |
| | | // ========== MES ä»åºç®¡ç-æé¡¹åºåºåï¼1-040-715-000ï¼ ========== |
| | | ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "æé¡¹åºåºåä¸åå¨"); |
| | | ErrorCode WM_MISC_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_715_001, "æé¡¹åºåºåç¼ç å·²åå¨"); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.enums.wm; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum MesWmStockStateEnum { |
| | | |
| | | TEMP(10, "æååº"), |
| | | QUALIFIED(20, "åæ ¼åº"), |
| | | OUT(30, "å·²åºåº"); |
| | | |
| | | private final Integer state; |
| | | private final String name; |
| | | } |
| | |
| | | */ |
| | | List<MesProBagCodeDO> getBagCodeListByBatchId(Long batchId); |
| | | |
| | | /** |
| | | * æ è®°è¢ç 为已åºåºï¼è®°å½éå®åºåºåç¼å·ååºåºæ¶é´ï¼ |
| | | * |
| | | * @param id è¢ç ç¼å· |
| | | * @param salesId éå®åºåºåç¼å· |
| | | */ |
| | | void markOutbound(Long id, Long salesId); |
| | | |
| | | /** |
| | | * æ¸
é¤è¢ç çåºåºæ è®°ï¼åæ¶åºåºåæ¶ä½¿ç¨ï¼ |
| | | * |
| | | * @param id è¢ç ç¼å· |
| | | */ |
| | | void clearOutbound(Long id); |
| | | |
| | | } |
| | |
| | | return bagCodeMapper.selectListByBatchId(batchId); |
| | | } |
| | | |
| | | @Override |
| | | public void markOutbound(Long id, Long salesId) { |
| | | bagCodeMapper.markOutbound(id, salesId, LocalDateTime.now()); |
| | | } |
| | | |
| | | @Override |
| | | public void clearOutbound(Long id) { |
| | | bagCodeMapper.clearOutbound(id); |
| | | } |
| | | |
| | | // ==================== ç§ææ¹æ³ ==================== |
| | | |
| | | /** |
| | |
| | | */ |
| | | void updatePalletBagCount(Long palletId, Integer bagCount); |
| | | |
| | | /** |
| | | * æ è®°æçç 为已åºåºï¼è®°å½éå®åºåºåç¼å·ååºåºæ¶é´ï¼ |
| | | * |
| | | * @param id æçç ç¼å· |
| | | * @param salesId éå®åºåºåç¼å· |
| | | */ |
| | | void markOutbound(Long id, Long salesId); |
| | | |
| | | /** |
| | | * æ¸
餿çç çåºåºæ è®°ï¼åæ¶åºåºåæ¶ä½¿ç¨ï¼ |
| | | * |
| | | * @param id æçç ç¼å· |
| | | */ |
| | | void clearOutbound(Long id); |
| | | |
| | | } |
| | |
| | | palletMapper.updateById(new MesProPalletDO().setId(palletId).setBagCount(bagCount)); |
| | | } |
| | | |
| | | @Override |
| | | public void markOutbound(Long id, Long salesId) { |
| | | palletMapper.markOutbound(id, salesId, java.time.LocalDateTime.now()); |
| | | } |
| | | |
| | | @Override |
| | | public void clearOutbound(Long id) { |
| | | palletMapper.clearOutbound(id); |
| | | } |
| | | |
| | | } |
| | |
| | | MesWmMaterialStockDO getMaterialStockByCompositeKey(Long itemId, Long warehouseId, Long locationId, Long areaId, |
| | | Long batchId, Long vendorId); |
| | | |
| | | List<MesWmMaterialStockDO> getMaterialStockListByItemAndBatch(Long itemId, Long batchId); |
| | | |
| | | /** |
| | | * æ´æ°åºåæ°é |
| | | * |
| | |
| | | */ |
| | | void updateMaterialStockQuantity(Long id, BigDecimal quantity, boolean checkFlag); |
| | | |
| | | void updateMaterialStockState(Long id, Integer stockState); |
| | | |
| | | /** |
| | | * åºä½æ··æ¾è§åæ ¡éª |
| | | * |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockStateEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | |
| | | .batchId(batchId).batchCode(batchCode).vendorId(vendorId) |
| | | .quantity(BigDecimal.ZERO) // åå§æ°é为 0ï¼ç± updateMaterialStockQuantity æ´æ° |
| | | .receiptTime(receiptTime != null ? receiptTime : LocalDateTime.now()) |
| | | .stockState(MesWmStockStateEnum.TEMP.getState()) |
| | | .frozen(false) |
| | | .build(); |
| | | materialStockMapper.insert(newStock); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MesWmMaterialStockDO> getMaterialStockListByItemAndBatch(Long itemId, Long batchId) { |
| | | return materialStockMapper.selectListByItemAndBatch(itemId, batchId); |
| | | } |
| | | |
| | | @Override |
| | | public void updateMaterialStockQuantity(Long id, BigDecimal quantity, boolean checkFlag) { |
| | | // æ´æ°åºåæ°éï¼Mapper å± CAS é²è´åºåï¼checkFlag=false æ¶å
è®¸è´æ°ï¼ |
| | | int updatedRows = materialStockMapper.updateQuantity(id, quantity, checkFlag); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void updateMaterialStockState(Long id, Integer stockState) { |
| | | materialStockMapper.updateById(new MesWmMaterialStockDO().setId(id).setStockState(stockState)); |
| | | } |
| | | |
| | | @Override |
| | | public void checkAreaMixingRule(Long areaId, Long itemId, Long batchId) { |
| | | // 1.1 æ ¡éªåºä½å¿
é¡»åå¨ |
| | | MesWmWarehouseAreaDO area = areaService.validateWarehouseAreaExists(areaId); |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanRespVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; |
| | | import jakarta.validation.Valid; |
| | | |
| | |
| | | */ |
| | | void stockProductSales(Long id); |
| | | |
| | | MesWmProductSalesScanRespVO scanProductSales(@Valid MesWmProductSalesScanReqVO reqVO); |
| | | |
| | | /** |
| | | * å¡«åè¿åï¼å¾
å¡«åè¿å â å¾
æ§è¡åºåºï¼ |
| | | * |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesScanRespVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; |
| | | import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; |
| | |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.stockreserve.MesWmStockReserveService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | |
| | | private MesWmProductSalesMapper productSalesMapper; |
| | | @Resource |
| | | private MesWmProductSalesLineMapper productSalesLineMapper; |
| | | @Resource |
| | | private MesWmProductSalesDetailMapper productSalesDetailMapper; |
| | | @Resource |
| | | private MesProBagCodeService bagCodeService; |
| | | @Resource |
| | | private MesProPalletService palletService; |
| | | @Resource |
| | | private MesProBatchService wmBatchService; |
| | | |
| | | @Resource |
| | | private MesWmProductSalesLineService productSalesLineService; |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public MesWmProductSalesScanRespVO scanProductSales(MesWmProductSalesScanReqVO reqVO) { |
| | | MesWmProductSalesDO sales = validateProductSalesExists(reqVO.getSalesId()); |
| | | if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.APPROVING.getStatus(), sales.getStatus())) { |
| | | throw exception(WM_PRODUCT_SALES_CANNOT_PICK); |
| | | } |
| | | MesProPalletDO pallet = palletService.getPalletByCode(reqVO.getScanContent()); |
| | | MesProBagCodeDO bag = pallet == null ? bagCodeService.getBagCodeByCode(reqVO.getScanContent()) : null; |
| | | if (pallet == null && bag == null) { |
| | | throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); |
| | | } |
| | | Long codeId = pallet != null ? pallet.getId() : bag.getId(); |
| | | MesWmProductSalesDetailDO existed = pallet != null |
| | | ? productSalesDetailMapper.selectBySalesIdAndPalletCodeId(reqVO.getSalesId(), codeId) |
| | | : productSalesDetailMapper.selectBySalesIdAndBagCodeId(reqVO.getSalesId(), codeId); |
| | | if (existed != null) { |
| | | return new MesWmProductSalesScanRespVO().setScanType(pallet != null ? "PALLET" : "BAG") |
| | | .setCodeId(codeId).setScanContent(reqVO.getScanContent()).setAlreadyScanned(true) |
| | | .setDetailId(existed.getId()).setOutboundQuantity(existed.getQuantity()).setMessage("该ç å·²æ«æ"); |
| | | } |
| | | Long batchId = pallet != null ? pallet.getBatchId() : bag.getBatchId(); |
| | | MesProBatchDO batch = wmBatchService.getBatch(batchId); |
| | | if (batch == null) { |
| | | throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS); |
| | | } |
| | | List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(reqVO.getSalesId()); |
| | | MesWmProductSalesLineDO line = lines.stream().filter(item -> ObjUtil.equal(item.getItemId(), batch.getItemId())).findFirst().orElse(null); |
| | | if (line == null) { |
| | | throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH); |
| | | } |
| | | BigDecimal quantity = reqVO.getQuantity(); |
| | | if (quantity == null) { |
| | | quantity = line.getQuantity(); |
| | | } |
| | | List<MesWmMaterialStockDO> stocks = materialStockService.getMaterialStockListByItemAndBatch(batch.getItemId(), batchId); |
| | | BigDecimal outboundQuantity = quantity; |
| | | MesWmMaterialStockDO stock = stocks.stream().filter(item -> item.getQuantity().compareTo(outboundQuantity) >= 0).findFirst().orElse(null); |
| | | if (stock == null) { |
| | | throw exception(WM_MATERIAL_STOCK_INSUFFICIENT); |
| | | } |
| | | BigDecimal scanned = productSalesDetailService.getProductSalesDetailListByLineId(line.getId()).stream() |
| | | .map(MesWmProductSalesDetailDO::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | if (scanned.add(quantity).compareTo(line.getQuantity()) > 0) { |
| | | throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_INVALID); |
| | | } |
| | | MesWmProductSalesDetailDO detail = new MesWmProductSalesDetailDO().setLineId(line.getId()) |
| | | .setSalesId(reqVO.getSalesId()).setItemId(batch.getItemId()).setQuantity(quantity) |
| | | .setMaterialStockId(stock.getId()).setBatchId(batchId).setBatchCode(batch.getCode()) |
| | | .setWarehouseId(stock.getWarehouseId()).setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId()) |
| | | .setBagCodeId(pallet == null ? codeId : null).setPalletCodeId(pallet != null ? codeId : null); |
| | | productSalesDetailMapper.insert(detail); |
| | | return new MesWmProductSalesScanRespVO().setScanType(pallet != null ? "PALLET" : "BAG") |
| | | .setCodeId(codeId).setScanContent(reqVO.getScanContent()).setItemId(batch.getItemId()) |
| | | .setBatchId(batchId).setBatchCode(batch.getCode()).setMaterialStockId(stock.getId()) |
| | | .setAvailableQuantity(stock.getQuantity()).setScanQuantity(quantity).setOutboundQuantity(quantity) |
| | | .setAlreadyScanned(false).setDetailId(detail.getId()).setWarehouseId(stock.getWarehouseId()) |
| | | .setLocationId(stock.getLocationId()).setAreaId(stock.getAreaId()).setMessage("æ«ç æå"); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void stockProductSales(Long id) { |
| | | // æ ¡éªåå¨ |
| | | MesWmProductSalesDO sales = validateProductSalesExists(id); |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.transaction.MesWmTransactionMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockStateEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; |
| | |
| | | // 2.3 æ´æ°åºåæ°é |
| | | boolean checkFlag = ObjUtil.defaultIfNull(reqDTO.getCheckFlag(), true); |
| | | materialStockService.updateMaterialStockQuantity(materialStock.getId(), reqDTO.getQuantity(), checkFlag); |
| | | MesWmMaterialStockDO updatedStock = materialStockService.getMaterialStock(materialStock.getId()); |
| | | BigDecimal newQuantity = updatedStock.getQuantity(); |
| | | materialStockService.updateMaterialStockState(updatedStock.getId(), newQuantity.signum() <= 0 |
| | | ? MesWmStockStateEnum.OUT.getState() : MesWmStockStateEnum.QUALIFIED.getState()); |
| | | |
| | | // 3. æå
¥äºå¡æµæ°´ |
| | | MesWmTransactionDO transaction = MesWmTransactionDO.builder() |