feat(approve): 实现审批流程或签会签功能并优化数据库配置
- 添加审批模式字段支持或签和会签
- 实现同节点多审批人的分组处理逻辑
- 重构审批节点初始化和状态更新流程
- 优化审批流程查询和排序逻辑
- 添加用印审批类型支持和导出功能
- 集成审批节点附件管理功能
- 优化数据库连接配置参数
- 更新项目依赖配置文件
| | |
| | |
|
| | | ### STS ###
|
| | | .apt_generated
|
| | | .claude
|
| | | .classpath
|
| | | .factorypath
|
| | | .project
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # inspectiontask 模åé»è¾è¯´æ |
| | | |
| | | ## 1. 模åå®ä½ |
| | | |
| | | `inspectiontask` æ¯ä¸ä¸ªå´ç»â宿¶çæå·¡æ£ä»»å¡ã人工å½å
¥å·¡æ£ç»æãæ«ç è®°å½ççâçä¸å¡æ¨¡åã宿巡æ£è®¡åãå·¡æ£åãäºç»´ç ãæ«ç è®°å½åç±»è½å串æä¸æ¡éç¯ã |
| | | |
| | | æ ¸å¿ç®æ æä¸ä¸ªï¼ |
| | | |
| | | 1. ç»´æ¤å·¡æ£è®¡åï¼å¹¶éè¿ Quartz 宿¶è§¦åã |
| | | 2. çæå·¡æ£åï¼æ¯æäººå·¥è¡¥å½ãç¼è¾ã导åºãå é¤ã |
| | | 3. è®°å½äºç»´ç 䏿«ç è¡ä¸ºï¼ä½ä¸ºå·¡æ£ç°åºçè¾
å©å°è´¦ã |
| | | |
| | | ## 2. 模åæå |
| | | |
| | | ### 2.1 宿¶å·¡æ£ä»»å¡ |
| | | |
| | | 对åºç±»ï¼ |
| | | |
| | | - `TimingTaskController` |
| | | - `TimingTaskService` |
| | | - `TimingTaskServiceImpl` |
| | | - `TimingTaskScheduler` |
| | | - `TimingTaskJob` |
| | | - `QuartzConfig` |
| | | |
| | | èè´£ï¼ |
| | | |
| | | - ç»´æ¤å·¡æ£è®¡åã |
| | | - 计ç®é¦æ¬¡æ§è¡æ¶é´å䏿¬¡æ§è¡æ¶é´ã |
| | | - æå·¡æ£è®¡å注åå° Quartzã |
| | | - å°ç¹åèªå¨çæå·¡æ£ä»»å¡ã |
| | | |
| | | ### 2.2 å·¡æ£ä»»å¡è®°å½ |
| | | |
| | | 对åºç±»ï¼ |
| | | |
| | | - `InspectionTaskController` |
| | | - `InspectionTaskService` |
| | | - `InspectionTaskServiceImpl` |
| | | |
| | | èè´£ï¼ |
| | | |
| | | - æ¥è¯¢å·¡æ£ä»»å¡å表ã |
| | | - æ¥çæä¸ªå®æ¶ä»»å¡ä¸çå·¡æ£è®°å½ã |
| | | - æ¹éæ°å¢æç¼è¾å·¡æ£ä»»å¡ã |
| | | - å é¤å·¡æ£ä»»å¡åå
¶å
³èéä»¶ã |
| | | |
| | | ### 2.3 äºç»´ç 管ç |
| | | |
| | | 对åºç±»ï¼ |
| | | |
| | | - `QrCodeController` |
| | | - `QrCodeService` |
| | | - `QrCodeServiceImpl` |
| | | |
| | | èè´£ï¼ |
| | | |
| | | - ç»´æ¤äºç»´ç åºç¡ä¿¡æ¯ã |
| | | - æä¾å表ã墿¹ãå é¤è½åã |
| | | |
| | | ### 2.4 æ«ç è®°å½ç®¡ç |
| | | |
| | | 对åºç±»ï¼ |
| | | |
| | | - `QrCodeScanRecordController` |
| | | - `QrCodeScanRecordService` |
| | | - `QrCodeScanRecordServiceImpl` |
| | | |
| | | èè´£ï¼ |
| | | |
| | | - è®°å½äºç»´ç æ«ç è¡ä¸ºã |
| | | - å
³èäºç»´ç ä¿¡æ¯ä¸éä»¶ä¿¡æ¯ã |
| | | - æ¯æå表ã墿¹ãå é¤ã |
| | | |
| | | ## 3. 主ä¸å¡æµç¨ |
| | | |
| | | ### 3.1 宿¶ä»»å¡å建ä¸å¯å |
| | | |
| | | å端éè¿ `POST /timingTask/addOrEditTimingTask` å建æä¿®æ¹å·¡æ£è®¡åã |
| | | |
| | | å端å¤çé¡ºåºæ¯ï¼ |
| | | |
| | | 1. å¤å¶è¯·æ±æ°æ®å° `TimingTask`ã |
| | | 2. æ ¹æ®éæ©ç设å¤å表补é½ä»»å¡åç§°ãåºåã设å¤ä¸²çä¿¡æ¯ã |
| | | 3. 计ç®é¦æ¬¡æ§è¡æ¶é´ã |
| | | 4. ä¿åå°æ°æ®åºã |
| | | 5. 忥 Quartz è°åº¦ç¶æã |
| | | |
| | | 妿åç»è°ç¨ `POST /timingTask/changeEnable`ï¼ |
| | | |
| | | 1. å
æ´æ°æ°æ®åºéçå¯ç¨ç¶æã |
| | | 2. åéæ°æ³¨åæå·æ° Quartz 触åå¨ã |
| | | 3. å¯ç¨æ¶æ¢å¤æ§è¡ï¼ç¦ç¨æ¶æåæ§è¡ã |
| | | |
| | | å 餿¶ä¼å
å 餿°æ®åºè®°å½ï¼åä» Quartz ä¸åæ¶å¯¹åºä»»å¡ã |
| | | |
| | | ### 3.2 宿¶çæå·¡æ£å |
| | | |
| | | Quartz å°ç¹å触å `TimingTaskJob`ã |
| | | |
| | | æ§è¡é»è¾æ¯ï¼ |
| | | |
| | | 1. éè¿ä»»å¡ ID 读åå½åå·¡æ£è®¡åã |
| | | 2. 妿任å¡å·²ç¦ç¨ï¼ç´æ¥éåºã |
| | | 3. è§£æè¯¥ä»»å¡ç»å®ç设å¤å表ã |
| | | 4. æè®¾å¤é个çæå·¡æ£åã |
| | | 5. æè®¾å¤æ°éå³å®çææ¬¡æ°ã |
| | | 6. åå
¥ `inspection_task`ã |
| | | 7. æ´æ°è¯¥å®æ¶ä»»å¡çæåæ§è¡æ¶é´å䏿¬¡æ§è¡æ¶é´ã |
| | | |
| | | è¿ä¸æ¥æ¯æ¨¡åçæ ¸å¿èªå¨åå
¥å£ã |
| | | |
| | | ### 3.3 å·¡æ£å人工å½å
¥ä¸å¼å¸¸èå¨ |
| | | |
| | | å端éè¿ `POST /inspectionTask/addOrEditInspectionTask` æ¹éæäº¤å·¡æ£åã |
| | | |
| | | å端é»è¾æ¯ï¼ |
| | | |
| | | 1. éæ¡ä¿åææ´æ°å·¡æ£åã |
| | | 2. è¥å·¡æ£ç»æä¸ºå¼å¸¸ï¼åæåºåæ¶éå¼å¸¸ä»»å¡ã |
| | | 3. å䏿¹æäº¤éï¼åä¸åºååªä¿ç䏿¡å¼å¸¸è®°å½ç¨äºåç»çæç»´ä¿®åã |
| | | 4. å¨å½å¤©èå´å
ï¼å¦æè¯¥åºåå·²ç»åå¨å¾
ç»´ä¿®åï¼åè·³è¿ï¼é¿å
éå¤çæã |
| | | 5. 妿ä¸åå¨ï¼åèªå¨åå»ºä¸æ¡ç»´ä¿®åã |
| | | |
| | | å æ¤ï¼è¿ä¸ªæ¨¡åä¸ä»
ä¿åå·¡æ£ç»æï¼è¿æ¿æ
âå·¡æ£å¼å¸¸ -> èªå¨çæç»´ä¿®ä»»å¡âçèå¨èè´£ã |
| | | |
| | | ### 3.4 å·¡æ£åå表å±ç¤º |
| | | |
| | | å·¡æ£åå表æ¥å£ä¼å䏿¬¡âæå®æ¶ä»»å¡èåâçæ´çï¼è䏿¯ç®åè¿åæ°æ®åºåå§è¡ã |
| | | |
| | | èåé»è¾å¤§è´æ¯ï¼ |
| | | |
| | | 1. æå®æ¶ä»»å¡ ID å½ç»ã |
| | | 2. åä¸ç»éåªè¿å䏿¡ä»£è¡¨è®°å½ã |
| | | 3. åå¹¶ä»»å¡åç§°ãå·¡æ£äººã夿³¨ãå°ç¹ãé¢ççå±ç¤ºä¿¡æ¯ã |
| | | 4. å并该ç»ä¸çéä»¶å表ã |
| | | 5. æå®æ¶ä»»å¡åå建æ¶é´æåºåå页è¿åã |
| | | |
| | | æä»¥å表页çå°çæ¯âä¸å¡è§è§çå·¡æ£ä»»å¡å¡çâï¼ä¸æ¯éæ¡åºå±è®°å½ã |
| | | |
| | | ### 3.5 å·¡æ£è®°å½æå®æ¶ä»»å¡æ¥è¯¢ |
| | | |
| | | `GET /timingTask/recordList/{timingId}` 伿¥è¯¢æä¸ªå®æ¶ä»»å¡å¨å½å¤©çæçå·¡æ£è®°å½ã |
| | | |
| | | è¿éçèå´éå®ä¸ºå½å¤©ï¼æ¯ä¸ºäºè®©é¡µé¢æ¥çâ仿¥æ§è¡æ
åµâæ´ç´æ¥ã |
| | | |
| | | ### 3.6 äºç»´ç 䏿«ç è®°å½ |
| | | |
| | | äºç»´ç 模ååªè´è´£äºç»´ç æ¬èº«çå¢å æ¹æ¥ã |
| | | |
| | | æ«ç è®°å½æ¨¡åè´è´£ææ«ç è¡ä¸ºãæ«ç 人ãäºç»´ç ä¿¡æ¯ãéä»¶ä¿¡æ¯ä¸²èµ·æ¥ï¼ |
| | | |
| | | 1. å
åé¡µæ¥æ«ç è®°å½ã |
| | | 2. 忹鿥å
³èäºç»´ç ã |
| | | 3. 忹鿥å
³èéä»¶ã |
| | | 4. 忥é件对åºçæä»¶å
æ°æ®ã |
| | | 5. æåç»è£
æå端å¯ç´æ¥å±ç¤ºç DTOã |
| | | |
| | | å®çè§è²æ´åâå·¡æ£ç°åºçè¾
å©ççæ¨¡åâã |
| | | |
| | | ## 4. è°åº¦ä¸æ¶é´è®¡ç® |
| | | |
| | | ### 4.1 Quartz æ¥å
¥æ¹å¼ |
| | | |
| | | `QuartzConfig` æä¾äº `SchedulerFactoryBean` å `Scheduler`ï¼å¹¶éè¿èªå®ä¹ JobFactory æ¯æ Job å
é¨èªå¨æ³¨å
¥ Spring ä¾èµã |
| | | |
| | | `TimingTaskScheduler` è´è´£ï¼ |
| | | |
| | | - å建 JobDetailã |
| | | - å建 Triggerã |
| | | - éæ°è°åº¦ã |
| | | - æåãæ¢å¤ãå é¤ä»»å¡ã |
| | | |
| | | ### 4.2 æ¯æçé¢çç±»å |
| | | |
| | | 代ç 鿝æçé¢çç±»åå
æ¬ï¼ |
| | | |
| | | - `DAILY` |
| | | - `WEEKLY` |
| | | - `MONTHLY` |
| | | - `QUARTERLY` |
| | | - `YEARLY` |
| | | |
| | | æ¶é´è¡¨è¾¾å¼ç±æå¡å±åè°åº¦å±å
±åè§£æï¼æç»è½¬æ¢ä¸º Quartz cronã |
| | | |
| | | ### 4.3 éè¦æ³¨æçå®ç°ç»è |
| | | |
| | | 1. æå¡å±å Job å±é½åèªå®ç°äºä¸å¥â䏿¬¡æ§è¡æ¶é´â计ç®é»è¾ã |
| | | 2. Job 屿§è¡å®åï¼ä¼ç´æ¥æ´æ° `timing_task` çæåæ§è¡æ¶é´å䏿¬¡æ§è¡æ¶é´ã |
| | | 3. æå¡å±å¨æ°å¢ä»»å¡æ¶ä¼å
计ç®é¦æ¬¡æ§è¡æ¶é´ï¼ä½å£åº¦ç±»åå¨å½åå®ç°é馿¬¡æ¶é´è®¡ç®æ¹æ³ä¸ºç©ºï¼å±äºä¸ä¸ªéè¦æ³¨æçå®ç°ç¼ºå£ã |
| | | |
| | | ## 5. æ°æ®ä¸å
³èå
³ç³» |
| | | |
| | | è¿ä¸ªæ¨¡åç主è¦å
³èå
³ç³»å¯ä»¥çè§£ä¸ºï¼ |
| | | |
| | | - `TimingTask` æ¯å·¡æ£è®¡åã |
| | | - `InspectionTask` æ¯å·¡æ£æ§è¡è®°å½ã |
| | | - `QrCode` æ¯ç°åºäºç»´ç å°è´¦ã |
| | | - `QrCodeScanRecord` æ¯æ«ç è¡ä¸ºè®°å½ã |
| | | - å·¡æ£å¼å¸¸ä¼èå¨çæç»´ä¿®åã |
| | | - å·¡æ£ååæ«ç è®°å½é½ä¼å
³èéä»¶èµæºã |
| | | |
| | | ## 6. 对å端çæä¹ |
| | | |
| | | å端对è¿ä¸ªæ¨¡åçä½¿ç¨æ¹å¼å¯ä»¥æ¦æ¬ä¸ºï¼ |
| | | |
| | | 1. å
ç»´æ¤å·¡æ£è®¡åï¼åç±ç³»ç»èªå¨çæå·¡æ£åã |
| | | 2. å·¡æ£åæ¯æäººå·¥è¡¥å½ãç¼è¾ã导åºãå é¤ã |
| | | 3. 宿¶ä»»å¡æ¯æå¯ç¨ãç¦ç¨åéæ°è°åº¦ã |
| | | 4. å·¡æ£å¼å¸¸åï¼ç³»ç»ä¼èªå¨è¡¥ä¸æ¡ç»´ä¿®åï¼å端éè¦è½åæ¶å·æ°ç¸å
³é¡µé¢ã |
| | | 5. äºç»´ç åæ«ç è®°å½å±äºç¬ç«çè¾
å©ç®¡ç页é¢ã |
| | | |
| | | ## 7. æ¥å£æ»è§ |
| | | |
| | | ### å·¡æ£ä»»å¡ |
| | | |
| | | - `GET /inspectionTask/list` |
| | | - `POST /inspectionTask/export` |
| | | - `POST /inspectionTask/addOrEditInspectionTask` |
| | | - `DELETE /inspectionTask/delInspectionTask` |
| | | |
| | | ### 宿¶ä»»å¡ |
| | | |
| | | - `GET /timingTask/list` |
| | | - `GET /timingTask/recordList/{timingId}` |
| | | - `POST /timingTask/export` |
| | | - `POST /timingTask/addOrEditTimingTask` |
| | | - `POST /timingTask/changeEnable` |
| | | - `DELETE /timingTask/delTimingTask` |
| | | |
| | | ### äºç»´ç |
| | | |
| | | - `GET /qrCode/list` |
| | | - `POST /qrCode/addOrEditQrCode` |
| | | - `DELETE /qrCode/delQrCode` |
| | | |
| | | ### æ«ç è®°å½ |
| | | |
| | | - `GET /qrCodeScanRecord/list` |
| | | - `POST /qrCodeScanRecord/addOrEditQrCodeRecord` |
| | | - `DELETE /qrCodeScanRecord/delSalesRecord` |
| | | |
| | | ## 8. ç»è®º |
| | | |
| | | `inspectiontask` æ¨¡åæ¬è´¨ä¸æ¯ä¸æ¡â计å -> è°åº¦ -> çæå·¡æ£å -> å½å
¥ç»æ -> å¼å¸¸èå¨ç»´ä¿® -> ççæ¥è¯¢âçä¸å¡é¾è·¯ã |
| | | 妿åç»è¦ç»§ç»æåå端èè°ï¼ä¼å
å
³æ³¨ä¸åï¼å®æ¶ä»»å¡çæ¶é´è¡¨è¾¾å¼ãå·¡æ£ç»æçå¼å¸¸èå¨ã以åå·¡æ£å表çèåå±ç¤ºé»è¾ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ä¸åæ ¼ç®¡çæ¨¡åé»è¾åæ |
| | | |
| | | ## 1. 模åå®ä½ |
| | | |
| | | `quality` å
ä¸ç"ä¸åæ ¼ç®¡ç"æ¯ä¸ä¸ªç¬ç«çä¸å¡éç¯ï¼**æ£éª(è´¨æ£) â ä¸åæ ¼åç»è®° â ä¸åæ ¼åå¤ç â ä¸åæ ¼åå¤çå(å®¡æ¹æµ)**ãæ¤å¤è¿å
嫿£æµæ åç»´æ¤ãæ£éªæ¥åçæãè´¨éæ¥è¡¨ç»è®¡ä¸ä¸ªé
å¥è½åã |
| | | |
| | | æ ¸å¿ç®æ ï¼ |
| | | 1. è¦çåæææ£éªãè¿ç¨æ£éªãåºåæ£éªä¸ç§è´¨æ£åºæ¯ã |
| | | 2. æ£éªä¸åæ ¼æ¶èªå¨ç»è®°ä¸åæ ¼åï¼æ¯æè¿å·¥/è¿ä¿®/æ¥åº/è®©æ¥æ¾è¡åç§å¤çæ¹å¼ã |
| | | 3. ä¸åæ ¼åå¤çåèµ°å®¡æ¹æµç¨ï¼è稿âå¾
审æ¹â审æ¹ä¸â已宿/已驳åï¼ã |
| | | 4. æä¾åæ ¼çãæåº¦è¶å¿ãæ£æµææ æåçç»è®¡æ¥è¡¨ã |
| | | |
| | | --- |
| | | |
| | | ## 2. æ°æ®åºè¡¨ç»æ |
| | | |
| | | ### 2.1 quality_inspectï¼æ£éªè®°å½ä¸»è¡¨ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | inspect_type | INT | **å¿
å¡«**ã0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | |
| | | | inspect_state | INT | 0=æªæäº¤(è稿)ï¼1=å·²æäº¤ | |
| | | | check_time | DATE | æ£æµæ¥æ | |
| | | | supplier | VARCHAR | ä¾åºååç§°ï¼åæææ£éªä½¿ç¨ï¼ | |
| | | | customer | VARCHAR | 客æ·åç§°ï¼è¿ç¨/åºåæ£éªä½¿ç¨ï¼ | |
| | | | process | VARCHAR | å·¥åº/é¨ä»¶ç±»åï¼è¿ç¨æ£éªä½¿ç¨ï¼ | |
| | | | process_type | INT | å·¥åºç±»åï¼éå¹é
æ°æ®åå
¸ `product_process_type` | |
| | | | check_name | VARCHAR | æ£éªå | |
| | | | product_id | BIGINT | **å¿
å¡«**ãå
³è产åID | |
| | | | product_name | VARCHAR | 产ååç§° | |
| | | | model | VARCHAR | è§æ ¼åå· | |
| | | | unit | VARCHAR | åä½ | |
| | | | quantity | DECIMAL | æ°é | |
| | | | check_company | VARCHAR | æ£æµåä½ | |
| | | | check_result | VARCHAR | æ£æµç»æï¼"åæ ¼"/"ä¸åæ ¼"ï¼ | |
| | | | defective_phenomena | VARCHAR | ä¸åæ ¼ç°è±¡æè¿° | |
| | | | product_main_id | BIGINT | å
³èæ¥å·¥IDï¼è¿ç¨/åºåæ£éªä½¿ç¨ï¼ | |
| | | | product_model_id | BIGINT | å
³è产ååå·ID | |
| | | | purchase_ledger_id | BIGINT | å
³èéè´å°è´¦IDï¼åæææ£éªä½¿ç¨ï¼ | |
| | | | test_standard_id | BIGINT | å
³èæ£æµæ å主表ID | |
| | | | create_time | DATETIME | å建æ¶é´ï¼èªå¨å¡«å
ï¼ | |
| | | | create_user | INT | åå»ºç¨æ·ï¼èªå¨å¡«å
ï¼ | |
| | | | update_time | DATETIME | ä¿®æ¹æ¶é´ï¼èªå¨å¡«å
ï¼ | |
| | | | update_user | INT | ä¿®æ¹ç¨æ·ï¼èªå¨å¡«å
ï¼ | |
| | | | tenant_id | BIGINT | ç§æ·IDï¼èªå¨å¡«å
ï¼ | |
| | | | dept_id | BIGINT | é¨é¨IDï¼èªå¨å¡«å
ï¼ | |
| | | |
| | | ### 2.2 quality_inspect_paramï¼æ£éªåæ°æç»ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | parameter_item | VARCHAR | æ£æµææ åç§° | |
| | | | unit | VARCHAR | åä½ | |
| | | | standard_value | VARCHAR | æ åå¼ | |
| | | | control_value | VARCHAR | å
æ§å¼ | |
| | | | test_value | VARCHAR | æ£éªå¼ | |
| | | | inspect_id | BIGINT | **å¿
å¡«**ãå
³è quality_inspect.id | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | |
| | | > 䏿¡æ£éªè®°å½ (quality_inspect) 坹夿¡æ£éªåæ° (quality_inspect_param)ã |
| | | |
| | | ### 2.3 quality_inspect_fileï¼æ£éªéä»¶ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | name | VARCHAR | æä»¶åç§° | |
| | | | url | VARCHAR | æä»¶è·¯å¾ | |
| | | | file_size | INT | æä»¶å¤§å° | |
| | | | inspect_id | BIGINT | **å¿
å¡«**ãå
³è quality_inspect.id | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | |
| | | ### 2.4 quality_unqualifiedï¼ä¸åæ ¼åè®°å½ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | inspect_type | INT | **å¿
å¡«**ã0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | |
| | | | inspect_state | INT | **å¿
å¡«**ã0=å¾
å¤çï¼1=å·²å¤ç | |
| | | | check_time | DATE | æ£æµæ¥æ | |
| | | | check_name | VARCHAR | æ£éªå | |
| | | | product_id | BIGINT | å
³è产åID | |
| | | | product_name | VARCHAR | 产ååç§° | |
| | | | model | VARCHAR | è§æ ¼åå·ï¼åå¨çå¯è½æ¯ product_model.id æç´æ¥ææ¬ï¼ | |
| | | | unit | VARCHAR | åä½ | |
| | | | quantity | DECIMAL | æ°é | |
| | | | defective_phenomena | VARCHAR | ä¸åæ ¼ç°è±¡ | |
| | | | deal_result | VARCHAR | å¤çç»æï¼**"è¿ä¿®"/"è¿å·¥"/"æ¥åº"/"è®©æ¥æ¾è¡"** | |
| | | | deal_name | VARCHAR | å¤ç人 | |
| | | | deal_time | DATE | å¤çæ¥æ | |
| | | | reason_analysis | VARCHAR | åå åæ | |
| | | | preventive_corrective | VARCHAR | é¢é²ä¸çº æ£æªæ½ | |
| | | | loss_working | VARCHAR | å·¥æ¶æå¤± | |
| | | | loss_material | VARCHAR | ææè´¹æå¤± | |
| | | | inspect_id | BIGINT | å
³è quality_inspect.idï¼å¦ææ¯æ£éªä¸åæ ¼èªå¨çæï¼ | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | | temp_file_ids (èæ) | List\<String\> | ä¸´æ¶æä»¶IDå表ï¼ä»
ç¨äºæ¥æ¶åç«¯åæ°ï¼ | |
| | | | common_file_list (èæ) | List\<CommonFile\> | æ£å¼éä»¶åè¡¨ï¼æ¥è¯¢æ¶åå¡«ï¼ | |
| | | | method (èæ) | Boolean | æ è¯ model åæ®µæ¯å¦åå¨çæ¯ product_model.idï¼ç¨äºå表å±ç¤ºæ¶è§£æåå·ï¼ | |
| | | |
| | | ### 2.5 quality_unqualified_orderï¼åæåå·¥ä¸åæ ¼åå¤çåï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | order_no | VARCHAR | å¤çåç¼å·ï¼åç¼ "BHG"+ æ¥æ + åºå·ï¼èªå¨çæ | |
| | | | unqualified_id | BIGINT | å
³è quality_unqualified.id | |
| | | | project_name | VARCHAR | 项ç®åç§° | |
| | | | project_no | VARCHAR | 项ç®ç¼å· | |
| | | | equipment_id | BIGINT | å
³è设å¤ID | |
| | | | equipment_name | VARCHAR | 设å¤åç§° | |
| | | | equipment_drawing_no | VARCHAR | 设å¤å¾å· | |
| | | | material_name | VARCHAR | ç©æ/é¨ä»¶åç§° | |
| | | | product_model_id | BIGINT | å
³è产ååå·ID | |
| | | | material_drawing_no | VARCHAR | ç©æå¾å· | |
| | | | specification_model | VARCHAR | åå·è§æ ¼ | |
| | | | material_quality | VARCHAR | æè´¨ | |
| | | | quantity | DECIMAL | æ»æ°é | |
| | | | unqualified_quantity | DECIMAL | ä¸åæ ¼æ°é | |
| | | | unqualified_process | TINYINT | ä¸åæ ¼å·¥åºï¼1=æ¥æï¼2=å¶ç¨ï¼3=æå | |
| | | | supplier_name | VARCHAR | ä¾åºååç§° | |
| | | | inspector_name | VARCHAR | æ£éªå | |
| | | | inspect_date | DATE | æ£éªæ¥æ | |
| | | | responsible_person | VARCHAR | 责任人 | |
| | | | responsible_dept | VARCHAR | 责任é¨é¨ | |
| | | | problem_description | VARCHAR | é®é¢æè¿° | |
| | | | reason_analysis | VARCHAR | åå åæå建议 | |
| | | | correction_action | VARCHAR | çº æ£æªæ½ | |
| | | | disposal_method | TINYINT | å¤ç½®æ¹å¼ï¼1=è®©æ¥æ¥æ¶ï¼2=åå
ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åº | |
| | | | repair_evaluation | VARCHAR | åå
/è¿åç»´ä¿®è¯ä¼° | |
| | | | preventive_action | VARCHAR | é¢é²æªæ½ | |
| | | | status | TINYINT | ç¶æï¼0=è稿ï¼1=å¾
审æ¹ï¼2=审æ¹ä¸ï¼3=已宿ï¼4=已驳å | |
| | | | remark | VARCHAR | 夿³¨ | |
| | | | create_by / update_by / create_time / update_time / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | | deleted | TINYINT | é»è¾å é¤ï¼0=å¦ï¼1=æ¯ | |
| | | |
| | | ### 2.6 quality_test_standardï¼æ£æµæ åä¸»è¡¨ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | standard_no | VARCHAR | æ åç¼å· | |
| | | | standard_name | VARCHAR | æ ååç§° | |
| | | | state | VARCHAR | ç¶æ | |
| | | | remark | VARCHAR | 夿³¨ | |
| | | | inspect_type | INT | ç±»å«ï¼0=åæææ£éªï¼1=è¿ç¨æ£éªï¼2=åºåæ£éª | |
| | | | process_id | INT | å·¥åºID | |
| | | | process_type | INT | å·¥åºç±»å | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | |
| | | ### 2.7 quality_test_standard_paramï¼æ£æµæ ååæ°ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | BIGINT | 主é®ï¼èªå¢ | |
| | | | parameter_item | VARCHAR | åæ°é¡¹ï¼ææ åç§°ï¼ | |
| | | | unit | VARCHAR | åä½ | |
| | | | standard_value | VARCHAR | æ åå¼ | |
| | | | control_value | VARCHAR | å
æ§å¼ | |
| | | | default_value | VARCHAR | é»è®¤å¼ | |
| | | | test_standard_id | BIGINT | å
³è quality_test_standard.id | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | |
| | | ### 2.8 quality_test_standard_bindingï¼æ£æµæ å-产åå
³èï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | INT | 主é®ï¼èªå¢ | |
| | | | product_id | BIGINT | 产åID | |
| | | | test_standard_id | INT | å
³è quality_test_standard.id | |
| | | | create_time / update_time / create_user / update_user / tenant_id / dept_id | â | éç¨å®¡è®¡å段 | |
| | | |
| | | > å¤å¯¹å¤å
³ç³»ï¼ä¸ä¸ªäº§åå¯ç»å®å¤ä¸ªæ£æµæ åï¼ä¸ä¸ªæ£æµæ åå¯ç¨äºå¤ä¸ªäº§åã |
| | | |
| | | --- |
| | | |
| | | ## 3. æ ¸å¿ä¸å¡æµç¨ |
| | | |
| | | ### 3.1 è´¨æ£å®æ´é¾è·¯ |
| | | |
| | | ``` |
| | | æ£æµæ åç»´æ¤ â å建æ£éªå â 填忣éªåæ° â æäº¤æ£éª |
| | | â |
| | | ââââââââââââââââ´âââââââââââââââ |
| | | â â |
| | | ç»æ=ä¸åæ ¼ ç»æ=åæ ¼ |
| | | â â |
| | | èªå¨çæä¸åæ ¼åè®°å½ èªå¨åæ ¼å
¥åº |
| | | (quality_unqualified) (è°ç¨ StockUtils) |
| | | â |
| | | ä¸åæ ¼åå¤ç(deal) |
| | | â |
| | | âââââââââ¬âââââââââ¼âââââââââ |
| | | â â â â |
| | | è¿ä¿® è¿å·¥ æ¥åº è®©æ¥æ¾è¡ |
| | | (è¿ç¨/åºå) (å
¨é¨ç±»å) |
| | | â â â â |
| | | å
éç产 å
éç产 å
¥ä¸åæ ¼åº å
¥åæ ¼åº |
| | | 订å+路线 åä¸ (unqualified (qualified |
| | | +å·¥å stock) stock) |
| | | â |
| | | ä¸åæ ¼åå¤çå(approval flow) |
| | | è稿 â å¾
å®¡æ¹ â 审æ¹ä¸ â 已宿/已驳å |
| | | ``` |
| | | |
| | | ### 3.2 æ£éªæäº¤é»è¾ï¼QualityInspectServiceImpl.submitï¼ |
| | | |
| | | 1. æ ¡éª `checkResult` ä¸è½ä¸ºç©ºã |
| | | 2. 妿 `checkResult = "ä¸åæ ¼"`ï¼ |
| | | - èªå¨åå»ºä¸æ¡ `quality_unqualified` è®°å½ï¼`inspect_state=0`ï¼å¾
å¤çï¼ã |
| | | - ä¸åæ ¼ç°è±¡èªå¨çæä¸ºï¼æææ£éªåæ°åç§°æ¼æ¥ + "è¿äºææ ä¸åå¨ä¸åæ ¼"ã |
| | | 3. 妿 `checkResult = "åæ ¼"`ï¼ |
| | | - è°ç¨ `StockUtils.addStock()` ç´æ¥å
¥åºï¼å
¥åºç±»å `QUALITYINSPECT_STOCK_IN`ï¼ã |
| | | 4. å°æ£éªå `inspect_state` æ´æ°ä¸º 1ï¼å·²æäº¤ï¼ã |
| | | |
| | | ### 3.3 ä¸åæ ¼åå¤çé»è¾ï¼QualityUnqualifiedServiceImpl.dealï¼ |
| | | |
| | | æ ¸å¿åæ°ï¼`dealResult` å³å®å¤çè·¯å¾ï¼åä¸ºä¸¤å¤§åæ¯ã |
| | | |
| | | #### 忝Aï¼è¿ç¨æ£éª/åºåæ£éªï¼inspectType != 0 䏿 productMainIdï¼ |
| | | |
| | | | dealResult | å¤çé»è¾ | |
| | | |------------|----------| |
| | | | **"è¿ä¿®"æ"è¿å·¥"** | 1. æ ¹æ® `productMainId` æ¥å°åå§ç产订å(ProductOrder)ãå·¥èºè·¯çº¿ä¸»è¡¨(ProductProcessRoute)ãå·¥èºè·¯çº¿å表(ProductProcessRouteItem) | |
| | | | | 2. å
éä¸ä»½æ°çç产订åï¼quantity=ä¸åæ ¼æ°éï¼completeQuantity=0ï¼æ¶é´æ¸
ç©ºï¼ | |
| | | | | 3. å
éä¸ä»½æ°çå·¥èºè·¯çº¿ä¸»è¡¨ï¼å
³èæ°è®¢åï¼ | |
| | | | | 4. éæ¡å
éå·¥èºè·¯çº¿åè¡¨ï¼æ¯æ¡å
éåèªå¨çæå¯¹åºå·¥å(ProductWorkOrder)ï¼å·¥åå·è§å `"FG" + yyyyMMdd + 3ä½èªå¢åºå·` | |
| | | | **"æ¥åº"** | è°ç¨ `StockUtils.addUnStock()` å
¥ä¸åæ ¼åºï¼ç±»å `DEFECTIVE_SCRAP`ï¼ | |
| | | | **"è®©æ¥æ¾è¡"** | è°ç¨ `StockUtils.addStock()` å
¥åæ ¼åºï¼ç±»å `DEFECTIVE_PASS`ï¼ | |
| | | |
| | | #### 忝Bï¼åæææ£éªï¼inspectType == 0ï¼ |
| | | |
| | | | dealResult | å¤çé»è¾ | |
| | | |------------|----------| |
| | | | **"æ¥åº"** | å
éè¿ productName + model æ¥ product_model.idï¼åè°ç¨ `StockUtils.addUnStock()` å
¥ä¸åæ ¼åº | |
| | | | **"è®©æ¥æ¾è¡"** | å䏿¥æ¾ modelIdï¼åè°ç¨ `StockUtils.addStock()` å
¥åæ ¼åº | |
| | | | **"è¿ä¿®"/"è¿å·¥"** | åæææ£éªä¸æ¯æè¿ä¿®/è¿å·¥ï¼ä»£ç 䏿 æ¤åæ¯ï¼ä¸æ§è¡ä»»ä½æä½ï¼ | |
| | | |
| | | > å
³é®å¤æé»è¾ä½äº `QualityUnqualifiedServiceImpl.java:81`ï¼ |
| | | > ```java |
| | | > if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) |
| | | > ``` |
| | | > åªæå
³èäºæ£éªå䏿£éªç±»å䏿¯åææ(0)æ¶ï¼æèµ°è¿ç¨/åºåçå¤ç忝ï¼å
å«è¿ä¿®/è¿å·¥é»è¾ï¼ã |
| | | |
| | | å¤ç宿åå° `inspect_state` 置为 1ï¼å·²å¤çï¼ã |
| | | |
| | | ### 3.4 ä¸åæ ¼åå¤çåæµç¨ï¼QualityUnqualifiedOrderï¼ |
| | | |
| | | å¤ç忝坹ä¸åæ ¼åçæ£å¼å¤ç½®è®°å½ï¼å
嫿´ä¸°å¯çåæ®µå审æ¹ç¶ææºï¼ |
| | | |
| | | ``` |
| | | è稿(0) â å¾
审æ¹(1) â 审æ¹ä¸(2) â 已宿(3) |
| | | â â |
| | | å¯ç¼è¾/å é¤ å·²é©³å(4) |
| | | ``` |
| | | |
| | | - **ç¼å·èªå¨çæ**ï¼åç¼ `"BHG"` + 彿¥èªå¢åºå·ï¼éè¿ `OrderUtils.countTodayByCreateTime` å®ç°ï¼ã |
| | | - **å¤ç½®æ¹å¼æä¸¾**ï¼1=è®©æ¥æ¥æ¶ï¼2=åå
ç»´ä¿®ï¼3=è¿åç»´ä¿®ï¼4=æ¢è´§ï¼5=éè´§ï¼6=æ¥åºã |
| | | - **å页æ¥è¯¢**ï¼æ¯ææ statusãprojectNameãorderNo çéã |
| | | - **CRUD**ï¼æ¯ææ°å¢ãä¿®æ¹ãå é¤ï¼é»è¾å é¤éè¿ deleted åæ®µï¼ã |
| | | |
| | | ### 3.5 æ£éªåå é¤é»è¾ï¼QualityInspectController.delï¼ |
| | | |
| | | 1. æ ¡éªæ¯å¦å·²æäº¤ï¼`inspectState==1` ä¸å
许å é¤ï¼ã |
| | | 2. 级èå é¤å
³èçæ£éªåæ° (quality_inspect_param)ã |
| | | 3. 级èå é¤å
³èçæ£éªéä»¶ (quality_inspect_file)ã |
| | | 4. å 餿£éªåæ¬èº«ã |
| | | |
| | | ### 3.6 ä¸åæ ¼åå é¤é»è¾ï¼QualityUnqualifiedController.delï¼ |
| | | |
| | | 1. æ ¡éªæ¯å¦å·²å¤çï¼`inspectState==1` ä¸å
许å é¤ï¼ã |
| | | 2. 级èå é¤å
³èéä»¶ï¼éè¿ commonFileService æ businessId + type å é¤ï¼ã |
| | | 3. æ¹éå é¤ä¸åæ ¼åè®°å½ã |
| | | |
| | | ### 3.7 æ£æµæ åç»´æ¤ |
| | | |
| | | - æ£æµæ å主表 (quality_test_standard) ç»´æ¤æ åç¼å·ãåç§°ãéç¨æ£éªç±»åãå·¥åºç±»åã |
| | | - æ£æµæ ååæ° (quality_test_standard_param) ç»´æ¤ææ ãåä½ãæ åå¼ãå
æ§å¼ãé»è®¤å¼ã |
| | | - æ£æµæ å-产åç»å® (quality_test_standard_binding) å®ç°å¤å¯¹å¤å
³èã |
| | | - **å é¤ä¿æ¤**ï¼å 餿£æµæ åå伿£æ¥æ¯å¦è¢«æ£éªåå¼ç¨ï¼å¼ç¨åç¦æ¢å é¤ã |
| | | - **åæ°å¤å¶**ï¼æ¯æ `copyParam` å°æä¸ªæ åçåæ°å¤å¶å°å¦ä¸ä¸ªæ åã |
| | | - **å®¡æ ¸**ï¼æä¾ `qualityTestStandardAudit` æ¥å£ã |
| | | |
| | | --- |
| | | |
| | | ## 4. API æ¥å£æ»è§ |
| | | |
| | | ### 4.1 æ£éªè®°å½ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/quality/qualityInspect/add` | æ°å¢æ£éªåï¼å«æ£éªåæ°ï¼ | |
| | | | DELETE | `/quality/qualityInspect/del` | æ¹éå 餿£éªåï¼çº§èå é¤åæ°åéä»¶ï¼ | |
| | | | GET | `/quality/qualityInspect/{id}` | æ¥ç详æ
ï¼å«æ£éªåæ°ï¼ | |
| | | | POST | `/quality/qualityInspect/update` | ä¿®æ¹æ£éªåï¼å
å æ§åæ°åææ°åæ°ï¼ | |
| | | | GET | `/quality/qualityInspect/listPage` | å页æ¥è¯¢ï¼æç±»å JOIN ä¸åä¸å¡è¡¨ï¼ | |
| | | | POST | `/quality/qualityInspect/export` | å¯¼åº Excelï¼ä¸åç±»åéèä¸ååï¼ | |
| | | | POST | `/quality/qualityInspect/submit` | æäº¤æ£éªï¼åæ ¼å
¥åº/ä¸åæ ¼ç»è®°ï¼ | |
| | | | POST | `/quality/qualityInspect/down` | ä¸è½½ Word æ£éªæ¥åï¼poi-tl æ¨¡æ¿æ¸²æï¼ | |
| | | |
| | | ### 4.2 ä¸åæ ¼å管ç |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/quality/qualityUnqualified/add` | æ°å¢ä¸åæ ¼åï¼æå·¥å½å
¥ï¼ç¶æ=å¾
å¤çï¼ | |
| | | | DELETE | `/quality/qualityUnqualified/del` | æ¹éå é¤ï¼å·²å¤çä¸å¯å ï¼ | |
| | | | GET | `/quality/qualityUnqualified/{id}` | 详æ
ï¼å«éä»¶åè¡¨ï¼ | |
| | | | POST | `/quality/qualityUnqualified/update` | ä¿®æ¹ä¸åæ ¼å | |
| | | | GET | `/quality/qualityUnqualified/listPage` | å页æ¥è¯¢ï¼æç±»åãç¶æã产ååãæ¥æçéï¼ | |
| | | | POST | `/quality/qualityUnqualified/export` | å¯¼åº Excel | |
| | | | POST | `/quality/qualityUnqualified/deal` | **å¤çä¸åæ ¼å**ï¼è¿ä¿®/è¿å·¥/æ¥åº/è®©æ¥æ¾è¡ï¼ | |
| | | |
| | | ### 4.3 ä¸åæ ¼åå¤çå |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | `/qualityUnqualifiedOrder/listPage` | å页æ¥è¯¢ï¼æ¯æ status/projectName/orderNo çéï¼ | |
| | | | POST | `/qualityUnqualifiedOrder/save` | æ°å¢ï¼èªå¨çæç¼å·ï¼ | |
| | | | PUT | `/qualityUnqualifiedOrder/update` | ä¿®æ¹ | |
| | | | DELETE | `/qualityUnqualifiedOrder/delete` | æ¹éå é¤ | |
| | | |
| | | ### 4.4 æ£æµæ å |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/qualityTestStandard/add` | æ°å¢æ£æµæ å | |
| | | | DELETE | `/qualityTestStandard/del` | å é¤ï¼æå¼ç¨æ¶ç¦æ¢ï¼ | |
| | | | POST | `/qualityTestStandard/update` | ä¿®æ¹ | |
| | | | GET | `/qualityTestStandard/listPage` | å页æ¥è¯¢ | |
| | | | POST | `/qualityTestStandard/copyParam` | å¤å¶åæ°å°å¦ä¸ä¸ªæ å | |
| | | | POST | `/qualityTestStandard/qualityTestStandardAudit` | å®¡æ ¸æ£æµæ å | |
| | | | GET | `/qualityTestStandard/getQualityTestStandardByProductId` | æäº§åIDè·åæ åï¼éè¿ç»å®è¡¨ JOINï¼ | |
| | | | GET | `/qualityTestStandard/getQualityTestStandardParamByTestStandardId` | ææ åIDè·ååæ°å表 | |
| | | |
| | | ### 4.5 æ£æµæ åç»å® |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/qualityTestStandardBinding/add` | æ°å¢ç»å® | |
| | | | DELETE | `/qualityTestStandardBinding/del` | å é¤ç»å® | |
| | | | GET | `/qualityTestStandardBinding/list` | æ¥è¯¢ç»å®å表 | |
| | | |
| | | ### 4.6 æ£æµæ ååæ° |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/qualityTestStandardParam/add` | æ°å¢åæ° | |
| | | | DELETE | `/qualityTestStandardParam/del` | å é¤åæ° | |
| | | | POST | `/qualityTestStandardParam/update` | ä¿®æ¹åæ° | |
| | | | GET | `/qualityTestStandardParam/list` | æ¥è¯¢åæ°å表 | |
| | | |
| | | ### 4.7 æ£éªåæ° |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | `/quality/qualityInspectParam/{inspectId}` | ææ£éªIDæ¥åæ°å表 | |
| | | | POST | `/quality/qualityInspectParam/update` | ä¿®æ¹åæ° | |
| | | | DELETE | `/quality/qualityInspectParam/del` | å é¤åæ° | |
| | | |
| | | ### 4.8 æ£éªéä»¶ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/quality/qualityInspectFile/add` | æ°å¢éä»¶ | |
| | | | DELETE | `/quality/qualityInspectFile/del` | å é¤éä»¶ | |
| | | | GET | `/quality/qualityInspectFile/listPage` | å页æ¥è¯¢ | |
| | | |
| | | ### 4.9 è´¨éæ¥è¡¨ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | `/qualityReport/getInspectStatistics` | æ£éªç»è®¡ï¼æåææ/åæå/æååç»çæ»æ°å宿æ°ï¼ | |
| | | | GET | `/qualityReport/getPassRateStatistics` | åæ ¼çç»è®¡ï¼æææ±æ»ï¼æ»æ°ã宿æ°ãåæ ¼æ°ãä¸åæ ¼æ°ã宿çãåæ ¼çï¼ | |
| | | | GET | `/qualityReport/getMonthlyPassRateStatistics` | æåº¦åæ ¼çï¼12个æ à 3ç±»ï¼CTEéå½ï¼ | |
| | | | GET | `/qualityReport/getYearlyPassRateStatistics` | å¹´åº¦åæ ¼ç | |
| | | | GET | `/qualityReport/getMonthlyCompletionDetails` | æåº¦å®ææç»ï¼æ¯æåææ/åæå/æå宿æ°ï¼ | |
| | | | GET | `/qualityReport/getTopParameters` | æ£æµææ æåï¼Top 4 + å
¶ä»æ±æ»ï¼ | |
| | | |
| | | --- |
| | | |
| | | ## 5. å
³é®æ°æ®å
³è |
| | | |
| | | ``` |
| | | product (产ååç±») |
| | | âââ product (å
·ä½äº§å) |
| | | âââ product_model (产ååå·) |
| | | âââ quality_inspect.product_model_id |
| | | âââ quality_unqualified (éè¿ model åæ®µå
³è) |
| | | âââ quality_test_standard_binding.product_id |
| | | |
| | | production_product_main (ç产æ¥å·¥) |
| | | âââ quality_inspect.product_main_id (è¿ç¨/åºåæ£éª) |
| | | âââ production_product_main.work_order_id â product_work_order |
| | | âââ product_order â sales_ledger (éå®å°è´¦) |
| | | |
| | | purchase_ledger (éè´å°è´¦) |
| | | âââ quality_inspect.purchase_ledger_id (åæææ£éª) |
| | | |
| | | product_process_route (å·¥èºè·¯çº¿ä¸»è¡¨) |
| | | âââ product_process_route_item (å·¥èºè·¯çº¿å表) |
| | | âââ product_work_order (å·¥å) |
| | | ``` |
| | | |
| | | ### å页æ¥è¯¢æ¶ JOIN çç¥ |
| | | |
| | | - **åæææ£éª (inspectType=0)**ï¼LEFT JOIN `purchase_ledger` è·åéè´ååå·ã |
| | | - **è¿ç¨/åºåæ£éª (inspectType != 0)**ï¼LEFT JOIN `production_product_main` â `product_work_order` â `product_order` â `sales_ledger` è·åå·¥åå·åéå®ååå·ã |
| | | - **ä¸åæ ¼åå表**ï¼LEFT JOIN `product_model` è§£æåå·ï¼model åæ®µå¯è½æ¯ ID æææ¬ï¼ã |
| | | |
| | | --- |
| | | |
| | | ## 6. ä¸å¤é¨æ¨¡åçäº¤äº |
| | | |
| | | | 交äºç¹ | è°ç¨æ¹å¼ | 说æ | |
| | | |--------|----------|------| |
| | | | åºå管ç (stock) | `StockUtils.addStock()` / `StockUtils.addUnStock()` | åæ ¼å
¥åº / ä¸åæ ¼å
¥åº | |
| | | | ç产管ç (production) | ç´æ¥æä½ Mapper | è¿å·¥/è¿ä¿®æ¶å
éç产订å+å·¥èºè·¯çº¿+å·¥å | |
| | | | é件管ç (commonFile) | `CommonFileService` / `TempFileService` | ä¸´æ¶æä»¶è½¬æ£å¼æä»¶ãæä¸å¡ID+ç±»åæ¥è¯¢å é¤ | |
| | | | æ°æ®åå
¸ (dict) | `DictUtils` | processType æ ¡éªï¼å¯¼åºæ¶ translate | |
| | | | éè´å°è´¦ (procurement) | `ProcurementRecordService` | åæææ£éªå
³èéè´è®°å½ | |
| | | |
| | | --- |
| | | |
| | | ## 7. æä¸¾å¼æ±æ» |
| | | |
| | | ### inspectTypeï¼æ£éªç±»å«ï¼ |
| | | | å¼ | å«ä¹ | |
| | | |----|------| |
| | | | 0 | åæææ£éª | |
| | | | 1 | è¿ç¨æ£éª | |
| | | | 2 | åºåæ£éª | |
| | | |
| | | ### inspectStateï¼æ£éªåç¶æ / ä¸åæ ¼åç¶æï¼ |
| | | | å¼ | å«ä¹ï¼æ£éªåï¼ | å«ä¹ï¼ä¸åæ ¼åï¼ | |
| | | |----|---------------|------------------| |
| | | | 0 | æªæäº¤(è稿) | å¾
å¤ç | |
| | | | 1 | å·²æäº¤ | å·²å¤ç | |
| | | |
| | | ### dealResultï¼ä¸åæ ¼åå¤çç»æï¼ |
| | | | å¼ | å«ä¹ | éç¨åºæ¯ | |
| | | |----|------|----------| |
| | | | è¿ä¿® | è¿ä¿®å¤ç | ä»
è¿ç¨/åºåæ£éª | |
| | | | è¿å·¥ | è¿å·¥å¤çï¼é建ç产订åï¼ | ä»
è¿ç¨/åºåæ£éª | |
| | | | æ¥åº | å
¥ä¸åæ ¼åº | å
¨é¨ç±»å | |
| | | | è®©æ¥æ¾è¡ | å
¥åæ ¼åº | å
¨é¨ç±»å | |
| | | |
| | | ### disposalMethodï¼å¤çåå¤ç½®æ¹å¼ï¼ |
| | | | å¼ | å«ä¹ | |
| | | |----|------| |
| | | | 1 | è®©æ¥æ¥æ¶ | |
| | | | 2 | åå
ç»´ä¿® | |
| | | | 3 | è¿åç»´ä¿® | |
| | | | 4 | æ¢è´§ | |
| | | | 5 | éè´§ | |
| | | | 6 | æ¥åº | |
| | | |
| | | ### unqualifiedProcessï¼ä¸åæ ¼å·¥åºï¼ |
| | | | å¼ | å«ä¹ | |
| | | |----|------| |
| | | | 1 | æ¥æ | |
| | | | 2 | å¶ç¨ | |
| | | | 3 | æå | |
| | | |
| | | ### statusï¼å¤çåç¶æï¼ |
| | | | å¼ | å«ä¹ | |
| | | |----|------| |
| | | | 0 | è稿 | |
| | | | 1 | å¾
å®¡æ¹ | |
| | | | 2 | 审æ¹ä¸ | |
| | | | 3 | 已宿 | |
| | | | 4 | 已驳å | |
| | | |
| | | --- |
| | | |
| | | ## 8. ææ¯å®ç°è¦ç¹ |
| | | |
| | | 1. **MyBatis-Plus èªå¨å¡«å
**ï¼create_timeãcreate_userãupdate_timeãupdate_userãtenant_idãdept_id åéè¿ `@TableField(fill = ...)` èªå¨å¡«å
ã |
| | | 2. **äºå¡ç®¡ç**ï¼`QualityInspectServiceImpl` æ æ³¨ `@Transactional(rollbackFor = Exception.class)`ï¼ç¡®ä¿æ°å¢/ä¿®æ¹æ£éªåä¸åæ°æä½çååæ§ã |
| | | 3. **Word æ¥åçæ**ï¼ä½¿ç¨ poi-tl 模æ¿å¼æï¼æ¨¡æ¿æä»¶ `/static/report-template.docx`ï¼éè¿ `HackLoopTableRenderPolicy` 渲æåæ°åè¡¨è¡¨æ ¼ã |
| | | 4. **Excel 导åºå¨æå**ï¼æ ¹æ® inspectType 卿éèä¸ç¸å
³åï¼åæææ£éªéè customer/processï¼åºåæ£éªéè supplier/customer/processï¼ã |
| | | 5. **æåº¦ç»è®¡ CTE**ï¼`getMonthlyPassRateStatistics` ä½¿ç¨ MySQL WITH RECURSIVE çæ 1-12 æåºåï¼CROSS JOIN 3 ç§äº§åç±»åï¼LEFT JOIN å®é
æ°æ®ï¼ç¡®ä¿æ¯ææ¯ç±»åé½ææ°æ®è¡ã |
| | | 6. **ä¸åæ ¼å model åæ®µå
¼å®¹**ï¼model åæ®µå¯è½åå¨ product_model.idï¼æ°åï¼æç´æ¥ææ¬ï¼æ¥è¯¢æ¶ LEFT JOIN product_model å°è¯è§£æï¼å¹¶ç¨ method åæ®µæ è®°ã |
| | | 7. **è¿å·¥å·¥åå·çæ**ï¼æ¥æåç¼ `yyyyMMdd` + 3 ä½èªå¢åºå·ï¼åç¼ `"FG"`ï¼éè¿æ¥è¯¢å½æ¥æå¤§å·¥åå·å®ç°èªå¢ã |
| | | 8. **æä»¶ç®¡ç**ï¼åç«¯ä¼ tempFileIdsï¼å端éè¿ `TempFileService.migrateTempFilesToFormal()` å°ä¸´æ¶æä»¶è½¬ä¸ºæ£å¼æä»¶å¹¶ç»å®å°ä¸å¡IDã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å®¡æ¹æµç¨æ¯ææç¾/ä¼ç¾æ¨¡å¼ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - 审æ¹ç®¡çé
置页ï¼`collaborativeApproval/approvalManagement/index.vue` |
| | | - 审æ¹å表页ï¼åå审æ¹ï¼ï¼`collaborativeApproval/approvalProcess/index.vue` |
| | | - 审æ¹å表页ï¼å±é©ä½ä¸ type 8ï¼ï¼`safeProduction/safeWorkApproval/index.vue` |
| | | - 审æ¹å¼¹æ¡ï¼åå审æ¹ï¼ï¼`collaborativeApproval/approvalProcess/components/approvalDia.vue` |
| | | - 审æ¹å¼¹æ¡ï¼å±é©ä½ä¸ type 8ï¼ï¼`safeProduction/safeWorkApproval/components/approvalDia.vue` |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /approveProcessConfigNode/listNode | æ¥è¯¢å®¡æ¹èç¹é
ç½®ï¼ååºæ°å¢ `approveMode` åæ®µï¼ | |
| | | | POST | /approveProcessConfigNode/addApproveProcessConfigNodes | ä¿åèç¹é
ç½®ï¼æ¯è¡ä¸ä¸ªå®¡æ¹äººï¼åä¸ `nodeOrder` å¤è¡å³åä¸èç¹å¤äººï¼éä¼ `approveMode`ï¼ | |
| | | | POST | /approveProcess/addApprove | å起审æ¹ï¼æ°å¢ååº/å¿«ç
§å段 `approve_node_config`ï¼èç¹å«å¤äººæ¶åå
¥ `approve_user_current_ids/names`ï¼ | |
| | | | GET | /approveProcess/details | 审æ¹è¯¦æ
ï¼èç¹å表æ°å¢ `approveMode` åæ®µï¼`isShen` ä»
å½åå¾
审èç¹ä¸å½åç»å½äººå¯å®¡æ¶è¿å trueï¼ | |
| | | | POST | /approveNode/updateApproveNode | æäº¤å®¡æ¹ï¼**ä¸åéè¦ `isLast` åæ°**ï¼æµè½¬å¤æç±å端æèç¹æ¨¡å¼å®æï¼ | |
| | | |
| | | ### èç¹é
ç½®ä¿å请æ±åæ°ï¼addApproveProcessConfigNodesï¼ |
| | | |
| | | åä¸èç¹å¤å®¡æ¹äººéè¿å¤æ¡è®°å½è¡¨è¾¾ï¼`nodeOrder` ç¸åã`approveMode` æ è¯æ¨¡å¼ï¼ |
| | | |
| | | ```json |
| | | [ |
| | | { "approveType": 1, "nodeOrder": 1, "approverId": 11, "approverName": "å¼ ä¸", "approveMode": "or" }, |
| | | { "approveType": 1, "nodeOrder": 1, "approverId": 12, "approverName": "æå", "approveMode": "or" }, |
| | | { "approveType": 1, "nodeOrder": 2, "approverId": 21, "approverName": "çäº", "approveMode": "and" }, |
| | | { "approveType": 1, "nodeOrder": 2, "approverId": 22, "approverName": "èµµå
", "approveMode": "and" } |
| | | ] |
| | | ``` |
| | | |
| | | - `approveMode`ï¼`or`=æç¾ï¼ä»»ä¸äººéè¿å³æµè½¬ï¼ï¼`and`=ä¼ç¾ï¼éææäººéè¿ææµè½¬ï¼ |
| | | - ä»»ä¸å®¡æ¹äººæç» â æ´ä¸ªæµç¨ç«å³é©³åï¼æç¾/ä¼ç¾ä¸è´ï¼ä¸ç¥¨å¦å³ï¼ |
| | | |
| | | ### 审æ¹è¯¦æ
ååºï¼detailsï¼æ°å¢å段 |
| | | |
| | | æ¯ä¸ªèç¹æ°å¢ï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | approveMode | String | èç¹å®¡æ¹æ¨¡å¼ï¼or / and | |
| | | | approveNodeOrder | Integer | èç¹åºå·ï¼åä¸èç¹çå¤äººè®°å½ç¸åï¼ | |
| | | | isShen | Boolean | æ¯å¦ä¸ºå½åç»å½äººçå¾
审èç¹ | |
| | | |
| | | æµç¨çº§æ°å¢ï¼å表æ¥å£è¿åï¼ï¼`approveUserCurrentIds`ã`approveUserCurrentNames`ï¼å½åèç¹å
¨é¨å¾
审人ï¼ã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. é
置页ï¼èç¹å¡çæ¯æå¤å®¡æ¹äºº + æç¾/ä¼ç¾ |
| | | |
| | | `collaborativeApproval/approvalManagement/index.vue` |
| | | |
| | | 审æ¹äººæ¹ä¸ºå¤éï¼æ°å¢æ¨¡å¼åéï¼ |
| | | |
| | | ```html |
| | | <el-form-item label="审æ¹äºº"> |
| | | <el-select v-model="item.approverIds" multiple filterable placeholder="鿩审æ¹äººï¼å¯å¤éï¼"> |
| | | <el-option v-for="u in allUsers" :key="u.userId" :label="u.nickName" :value="u.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å®¡æ¹æ¨¡å¼"> |
| | | <el-radio-group v-model="item.approveMode"> |
| | | <el-radio-button value="or">æç¾ï¼ä»»æä¸äººéè¿ï¼</el-radio-button> |
| | | <el-radio-button value="and">ä¼ç¾ï¼éææäººéè¿ï¼</el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | ``` |
| | | |
| | | `loadData`ï¼å°æ¥å£æå¹³é
ç½®æ `nodeOrder` å并为å¡çæ°æ®ï¼ |
| | | |
| | | ```js |
| | | const groupMap = new Map(); |
| | | (res.data || []).forEach(r => { |
| | | const order = r.nodeOrder; |
| | | if (!groupMap.has(order)) groupMap.set(order, { nodeOrder: order, approverIds: [], approverNames: [], approveMode: r.approveMode || 'or' }); |
| | | const g = groupMap.get(order); |
| | | if (!g.approverIds.includes(r.approverId)) { |
| | | g.approverIds.push(r.approverId); |
| | | g.approverNames.push(r.approverName); |
| | | } |
| | | }); |
| | | nodeCards.value = Array.from(groupMap.values()).sort((a, b) => a.nodeOrder - b.nodeOrder); |
| | | ``` |
| | | |
| | | `handleSave`ï¼æ¯å¼ å¡çæå®¡æ¹äººå±å¼æå¤è¡ payloadï¼ |
| | | |
| | | ```js |
| | | const list = []; |
| | | nodeCards.value.forEach(card => { |
| | | card.approverIds.forEach((uid, i) => { |
| | | list.push({ |
| | | approveType: currentType, |
| | | nodeOrder: card.nodeOrder, |
| | | approverId: uid, |
| | | approverName: card.approverNames[i], |
| | | approveMode: card.approveMode || 'or', |
| | | }); |
| | | }); |
| | | }); |
| | | await addApproveProcessConfigNodes(list); |
| | | ``` |
| | | |
| | | ### 2. å表页ï¼å½å审æ¹äººå + å®¡æ ¸æé®æé |
| | | |
| | | `collaborativeApproval/approvalProcess/index.vue`ã`safeProduction/safeWorkApproval/index.vue` |
| | | |
| | | å½å审æ¹äººåå±ç¤ºåèç¹å
¨é¨å¾
审人ï¼å¯åè¡æ°æ®ï¼ |
| | | |
| | | ```js |
| | | tableData.value = (res.data.records || []).map(r => ({ |
| | | ...r, |
| | | currentApproverNames: r.approveUserCurrentNames || r.approveUserCurrentName || '-', |
| | | _canApprove: |
| | | String(r.approveUserCurrentIds ?? '').split(',').filter(Boolean).includes(String(userStore.id)) || |
| | | r.approveUserCurrentId === userStore.id, |
| | | })); |
| | | ``` |
| | | |
| | | å®¡æ ¸æé®ç¦ç¨æ¡ä»¶ï¼ |
| | | |
| | | ```js |
| | | disabled: row => |
| | | row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || !row._canApprove, |
| | | ``` |
| | | |
| | | ### 3. 审æ¹å¼¹æ¡ï¼æèç¹åç»å±ç¤º |
| | | |
| | | `collaborativeApproval/approvalProcess/components/approvalDia.vue`ã`safeProduction/safeWorkApproval/components/approvalDia.vue` |
| | | |
| | | æ°å¢åç»è®¡ç®å±æ§ï¼åä¸ `approveNodeOrder` çå¤å审æ¹äººå½ä¸ºä¸ä¸ªæ¥éª¤ç»ï¼ |
| | | |
| | | ```js |
| | | const stepGroups = computed(() => { |
| | | const map = new Map(); |
| | | (activities.value || []).forEach(a => { |
| | | const order = a.approveNodeOrder; |
| | | if (!map.has(order)) map.set(order, []); |
| | | map.get(order).push(a); |
| | | }); |
| | | return Array.from(map.values()); |
| | | }); |
| | | ``` |
| | | |
| | | `el-steps` æ¹ä¸ºéå `stepGroups`ï¼æ¯ç»ä¸ä¸ª `el-step`ï¼ç»å
å¾ªç¯æ¸²ææåï¼å§åãç¶æãæè§ãç¾åãå¾
审è¾å
¥æ¡ï¼ï¼ |
| | | |
| | | ```html |
| | | <el-steps :active="getActiveStep()" ...> |
| | | <el-step v-for="(group, gIndex) in stepGroups" :key="gIndex" ...> |
| | | <template #title> |
| | | <span>{{ getNodeTitle(gIndex, stepGroups.length) }}</span> |
| | | <el-tag :type="group[0]?.approveMode === 'and' ? 'warning' : 'info'"> |
| | | {{ group[0]?.approveMode === 'and' ? 'ä¼ç¾' : 'æç¾' }} |
| | | </el-tag> |
| | | </template> |
| | | <template #description> |
| | | <div v-for="(activity, aIndex) in group" :key="activity.id || aIndex" class="node-user-item"> |
| | | <!-- æåå§åãç¶æãå®¡æ¹æè§ï¼ä»
isShen æå渲æè¾å
¥æ¡ --> |
| | | </div> |
| | | </template> |
| | | </el-step> |
| | | </el-steps> |
| | | ``` |
| | | |
| | | å½åæ¿æ´»æ¥éª¤åå«å¾
审æåçç»ä¸æ ï¼ |
| | | |
| | | ```js |
| | | const getActiveStep = () => { |
| | | const idx = stepGroups.value.findIndex(group => group.some(a => a.isShen === true)); |
| | | if (idx === -1) return stepGroups.value.length; |
| | | return idx; |
| | | }; |
| | | ``` |
| | | |
| | | æäº¤å®¡æ¹ä¸åä¼ `isLast`ï¼ |
| | | |
| | | ```js |
| | | currentActivity.approveNodeStatus = status; |
| | | updateApproveNode({ ...currentActivity }).then(() => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }); |
| | | ``` |
| | | |
| | | ## 管çå审æ¹ä¸å审æ¹äººéå¶ |
| | | |
| | | 管çåè´¦å·ï¼è§è²ä¸º **æ®é2 / admin / æé«1**ï¼å¯å®¡æ¹ä»»ææµç¨ï¼ä¸åå"审æ¹äººå¿
é¡»æ¯æµç¨èç¹é
ç½®ç审æ¹äºº"éå¶ã |
| | | |
| | | ### å端 |
| | | |
| | | - `details`ï¼ç®¡çå对å½åå¾
审èç¹çé¦ä¸ªå¾
审记å½è¿å `isShen=true`ï¼ä»£å®¡æ´èç¹ï¼ã |
| | | - `updateApproveNode`ï¼ç®¡çåè·³è¿"æ æå®¡æ¹è¯¥èç¹"æ ¡éªï¼å®¡æ¹éè¿æ¶èªå¨å°åèç¹å
¶ä½å¾
å®¡è®°å½æ 记为"管çå代审éè¿"ï¼æç¾/ä¼ç¾åæ´èç¹æ¾è¡ï¼ï¼æç»ä»æä¸ç¥¨å¦å³å¤çã |
| | | |
| | | ### å端 |
| | | |
| | | 两个å表页ï¼approvalProcess / safeWorkApprovalï¼æ°å¢ `isAdminUser` å¤æï¼ |
| | | |
| | | ```js |
| | | const isAdminUser = computed(() => |
| | | ["admin", "æ®é2", "æé«1"].some(r => (userStore.roles || []).includes(r)) |
| | | ); |
| | | ``` |
| | | |
| | | `_canApprove` 对管çåæä¸º `true`ï¼å®¡æ ¸æé®ä¸åç¦ç¨ï¼ |
| | | |
| | | ```js |
| | | _canApprove: isAdminUser.value || String(r.approveUserCurrentIds ?? '').split(',').filter(Boolean).includes(String(userStore.id)) || r.approveUserCurrentId === userStore.id |
| | | ``` |
| | | |
| | | ### 注æ |
| | | |
| | | - 管çåä»éæèç¹é¡ºåºå®¡æ¹ï¼"å°æªè½®å°è¯¥èç¹å®¡æ¹"æ ¡éªä¿çï¼ã |
| | | - 管çåæç»ä»»æèç¹ = ä¸ç¥¨å¦å³ï¼æ´ä¸ªæµç¨ç«å³é©³åã |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - **å端æµè½¬å¤æ**ï¼`updateApproveNode` å·²æ¹ä¸ºæèç¹æ¨¡å¼ï¼æç¾/ä¼ç¾ï¼ç»è®¡å order çåææ°å³å®æ¯å¦æµè½¬ï¼å端**å¿
é¡»å é¤ `isLast` ä¼ å**ï¼å¦åæ§å段ä¼è¢«å¿½ç¥ï¼ä¸å½±åç»æï¼ä½æ æä¹ï¼ã |
| | | - **æç¾æ¾è¡**ï¼æç¾ä»»ä¸å®¡æ¹äººéè¿åï¼åèç¹å
¶ä½æªå®¡è®°å½ä¼è¢«å端èªå¨æ 记为"å·²åæï¼æç¾ï¼å
¶ä»å®¡æ¹äººå·²éè¿ï¼"ï¼å端æ éå¤çã |
| | | - **ä¼ç¾é¨åéè¿**ï¼èç¹åçå¨å½åæ¥éª¤ï¼å表"å½å审æ¹äºº"伿´æ°ä¸ºå©ä½æªå®¡äººåã |
| | | - **å岿°æ®å
¼å®¹**ï¼åéèç¹ `approveMode` 为空æ"æç¾"å¤çï¼åéæµç¨ `approveUserCurrentNames` 为空æ¶å端å
åº `approveUserCurrentName`ã |
| | | - **ç¼è¾é建**ï¼æµç¨ç¼è¾æ¶å端ä¼å
æ `approve_node_config` å¿«ç
§é建èç¹ä»¥ä¿æåç»ä¸æ¨¡å¼ï¼æ å¿«ç
§æ¶æ"ä¸èç¹ä¸äºº or"åéã |
| | | - é
置页已补å
**type 8 å±é©ä½ä¸å®¡æ¹** çæ ç¾ä¸å¾æ ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æäº§ä¸è¾¾èªå¨è§¦å第ä¸éå·¥åºè´¨æ£ |
| | | |
| | | ## åè½è¯´æ |
| | | |
| | | ç产æäº§ä¸è¾¾ï¼çæç产工åï¼åï¼è¥ç¬¬ä¸éå·¥åºéè¦è´¨æ£ï¼`isQuality=true`ï¼ï¼ç³»ç»èªå¨ä¸ºè¯¥å·¥åºé¢çæä¸å¼ è¿ç¨æ£éªï¼åéå·¥åºæ¶çæåºåæ£ï¼è´¨æ£åãè´¨æ£åæ éçå¾
è¯¥å·¥åºæ¥å·¥å®¡æ ¸å³å¯ç´æ¥å¨è´¨æ£å表ä¸å¼å§æ£éªã |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - ç产æäº§/ç产订åä¸è¾¾ |
| | | - è´¨æ£ç®¡çï¼è¿ç¨æ£éª / åºåæ£éª åè¡¨é¡µï¼ |
| | | |
| | | ## è¡ä¸ºååï¼çº¯åç«¯ï¼æ æ°å¢æ¥å£ï¼ |
| | | |
| | | ### 1. æäº§ä¸è¾¾èªå¨é¢çæè´¨æ£å |
| | | |
| | | è¦çå
¨é¨å·¥åå建å
¥å£ï¼ |
| | | |
| | | | å
¥å£ | 说æ | |
| | | |------|------| |
| | | | ç产订åç»å®å·¥èºè·¯çº¿ `bindingRoute` | çæå·¥ååé¢çæè´¨æ£å | |
| | | | éå®å°è´¦çæçäº§æ°æ® `addProductionData` | çæå·¥ååé¢çæè´¨æ£å | |
| | | | å°å·åéæ¶éåæ `processRouteAnticlockwise` | çæå·¥ååé¢çæè´¨æ£å | |
| | | |
| | | é¢çæè§åï¼ |
| | | |
| | | - åå·¥èºè·¯çº¿ç¬¬ä¸éå·¥åºï¼`dragSort` ååº + `id` ååºï¼ï¼ |
| | | - 第ä¸éå·¥åº `isQuality` é true åä¸çæï¼ |
| | | - ä»
ä¸éå·¥åº â `inspect_type=2`ï¼åºåæ£ï¼ï¼å¦å `inspect_type=1`ï¼è¿ç¨æ£ï¼`process`=第ä¸éå·¥åºåï¼ï¼ |
| | | - `quantity`=å·¥åè®¡åæ°éï¼ |
| | | - å
³é®å段ï¼`work_order_id`=第ä¸éå·¥åºå·¥å idï¼`product_main_id=NULL`ï¼æªå
³èæ¥å·¥ï¼ã |
| | | |
| | | > è¯å«é¢çæè´¨æ£åï¼`quality_inspect` è¡¨ä¸ `product_main_id IS NULL` ä¸ `work_order_id` é空çè®°å½å³ä¸ºæäº§é¢çæåã |
| | | |
| | | ### 2. æ¥å·¥å®¡æ ¸æ¶è®¤é¢å¹¶æ´æ° |
| | | |
| | | 第ä¸éå·¥åºæ¥å·¥å®¡æ ¸ï¼`nextAddProductMain`ï¼æ¶ï¼ |
| | | |
| | | - è¥è¯¥å·¥ååå¨é¢çæè´¨æ£åï¼`work_order_id` å¹é
ä¸ `product_main_id IS NULL`ï¼â **认é¢**ï¼åå¡« `product_main_id`=æ¥å·¥ idï¼`quantity` æ´æ°ä¸ºå®é
å
¥åºæ°éï¼äº§åº + å æ¾ - æ¥åºï¼ï¼ |
| | | - è¥è¯¥é¢çæåå·²æäº¤ï¼`inspect_state=1`ï¼ä¸ä¸ºåºåæ£ â å
å é¤æè®¡åæ°éå
¥åºçåºåè®°å½ï¼åæå®é
æ°ééæ°å
¥åºï¼ä¿è¯åºååç¡®ï¼ |
| | | - è¥ä¸åå¨é¢çæåï¼å¦å·¥åºä¸´æ¶æ°å¢ï¼â èµ°åæé»è¾çææ°è´¨æ£åã |
| | | |
| | | åç»å·¥åºï¼é第ä¸éï¼æ¥å·¥å®¡æ ¸æ¶ä»æåæé»è¾çæè´¨æ£åã |
| | | |
| | | ### 3. å表/æ¥åå±ç¤º |
| | | |
| | | - è´¨æ£å表çå·¥åå·éè¿ `COALESCE(qi.work_order_id, ppm.work_order_id)` å
³èï¼é¢çæåï¼æ æ¥å·¥ï¼ä¹è½æ£å¸¸æ¾ç¤ºå·¥åå·ï¼ |
| | | - æ£éªæ¥åä¸è½½ï¼é¢çæåï¼`product_main_id=NULL`ï¼æ `work_order_id` â ç产订å â éå®å°è´¦ 忥客æ·åç§°ã |
| | | |
| | | ### 4. å 餿¸
ç |
| | | |
| | | å é¤ç产订å / å é¤éå®å°è´¦çäº§æ°æ® / å é¤ç产工èºè·¯çº¿å·¥åºé¡¹æ¶ï¼èªå¨æ¸
ç对åºçé¢çæè´¨æ£ååå
¶æ£éªåæ°ï¼è¥é¢çæåå·²æäº¤ï¼`inspect_state=1`ï¼ï¼åæç»å é¤å¹¶æç¤ºâå·²æäº¤çæ£éªåä¸è½å é¤âã |
| | | |
| | | ## API |
| | | |
| | | æ æ°å¢ãæ ä¿®æ¹æ¥å£ãå为å端è¡ä¸ºåæ´ã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | æ åç«¯ä»£ç æ¹å¨ã |
| | | |
| | | è¥éå¨çé¢åºåâæäº§é¢çæâçè´¨æ£åï¼å¯åè `work_order_id`ï¼é空ï¼ä¸ `product_main_id` 为空è¿è¡å¤æã |
| | | |
| | | ## æ°æ®åºåæ´ |
| | | |
| | | æ§è¡ `sql/quality_inspect_add_work_order_id.sql`ï¼ |
| | | |
| | | ```sql |
| | | ALTER TABLE quality_inspect ADD COLUMN work_order_id BIGINT NULL COMMENT 'ç产工åid(æäº§é¢çæè´¨æ£åå
³è)' AFTER product_main_id; |
| | | ALTER TABLE quality_inspect ADD INDEX idx_quality_inspect_work_order_id (work_order_id); |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - é¢çæè´¨æ£åä»
é对**第ä¸ééè´¨æ£å·¥åº**ï¼ä¸éå·¥åºä»éæ¥å·¥å®¡æ ¸åæçæã |
| | | - è´¨æ£åå¯å¨æ¥å·¥åç´æ¥å¡«åæ£éªç»æå¹¶æäº¤ï¼åºåæ£æäº¤æ¶ä¼æè®¡åæ°éå
¥åºï¼æ¥å·¥å®¡æ ¸åèªå¨æå®é
æ°éä¿®æ£åºåã |
| | | - å·²æäº¤çé¢çæè´¨æ£åå¨å é¤è®¢å/å·¥åæ¶ä¼æç¤ºâå·²æäº¤çæ£éªåä¸è½å é¤âï¼éå
æ¤éæå 餿£éªåã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ç产æ¥å·¥æçç»æå产é/æ¶é¿ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - ç产工åå表页ï¼PDA æ¥å·¥å¼¹çªï¼æ°æ®æ¥æº `/productWorkOrder/getProductWorkOrderById`ï¼ |
| | | - æ¥å·¥æäº¤ï¼`POST /productionProductMain/addProductMain`ï¼ |
| | | - ç产æç»é¡µï¼ç产æç»å·¥æ¶åæ¾ï¼ |
| | | |
| | | ## API |
| | | |
| | | ### 1. æ¥å·¥å¼¹çªæ°æ®æ¥è¯¢ï¼è¿åé»è®¤çç»æåï¼ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /productWorkOrder/getProductWorkOrderById | æ¥å·¥å¼¹çªæ°æ®ï¼ååºæ°å¢ `reportPersons` é»è®¤çç»æåï¼åå¹¶å·¥åæäº§äººå䏿ºå°ä¸æºæä½åï¼å»éï¼ | |
| | | |
| | | **ååºæ°å¢å段ï¼** |
| | | |
| | | | åæ° | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | reportPersons | Array | æ¥å·¥çç»é»è®¤æåï¼æ¯é¡¹ `{ userId, userName }`ï¼ç¨ä½æ¥å·¥å¼¹çªå½å
¥è¡åå§å | |
| | | |
| | | ### 2. æ¥å·¥æäº¤ï¼æ°å¢ personList æç»ï¼ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | /productionProductMain/addProductMain | æ¥å·¥æäº¤ï¼è¯·æ±ä½æ°å¢ `personList` çç»äººåäº§éæ¶é¿æç» | |
| | | |
| | | **请æ±åæ°æ°å¢ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | personList | Array | æ¯ | çç»äººåäº§éæ¶é¿æç»ï¼æ¯é¡¹ `{ userId, userName, quantity, workHour }` | |
| | | | personList[].userId | Long | æ¯ | ç产人 id | |
| | | | personList[].userName | String | æ¯ | ç产人å§å | |
| | | | personList[].quantity | BigDecimal | æ¯ | 该人å产é | |
| | | | personList[].workHour | Integer | æ¯ | 该人åç产æ¶é¿ï¼åéï¼ | |
| | | |
| | | **æ ¡éªè§åï¼** å人å `quantity` ä¹åå¿
é¡»çäºæ¥å·¥æ»äº§é `quantity`ï¼å¦åå端è¿å `åçç»äº§éä¹åå¿
é¡»çäºæ¥å·¥æ»äº§é`ã |
| | | |
| | | ### 3. ç产æç»ï¼å·¥æ¶åæ¾ä¿®æ£ï¼ |
| | | |
| | | `/productionProductMain/page` 对åºçç产æç»ä¸ï¼æ°å¢ `personWorkMinutes` åæ®µç¨äºåæ¾åçç»äººåå½å
¥çå·¥æ¶ã |
| | | |
| | | **ååºæ°å¢å段ï¼** |
| | | |
| | | | åæ° | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | personWorkMinutes | String | åçç»äººåå½å
¥çç产æ¶é¿ï¼åéï¼ï¼æ¥æº `sales_ledger_production_accounting.work_hour` | |
| | | |
| | | ### 4. çäº§æ ¸ç®/æç»æ¥è¡¨äº§éåä¿®æ£ |
| | | |
| | | `GET /salesLedger/productionAccounting/listProductionDetails` æ¯è¡æç产人çæï¼ä¸äººä¸è¡ï¼ï¼"ç产æ°é"åæ®µ `quantity` ä¿®æ£ä¸ºï¼ |
| | | |
| | | - å¤äººæåæ¥å·¥ï¼`production_report_person` æè®°å½ï¼ï¼æ¾ç¤º**该ç产人æ¥å·¥æ¶è¾å
¥ç产é**ï¼`production_report_person.quantity`ï¼ï¼ä¸åæ¾ç¤ºæ´æ¡æ¥å·¥çæ»äº§éï¼ |
| | | - æªæå/å人æ¥å·¥ï¼åéæ¾ç¤ºæ ¸ç® `finished_num`ï¼åå¼ï¼ã |
| | | |
| | | ```sql |
| | | -- ä¿®æ£ååå¼ |
| | | COALESCE(prp.quantity, slpa.finished_num) AS quantity |
| | | -- å
³èæ¡ä»¶ï¼prp.product_main_id = ppm.id AND prp.user_id = slpa.scheduling_user_id |
| | | ``` |
| | | |
| | | `GET /salesLedger/productionAccounting/page`ï¼å·¦ä¾§æäººæ±æ»å°è´¦ï¼ç"产é"åæ®µ `output_num` åæ ·ä¿®æ£ï¼ |
| | | |
| | | - åï¼`SUM(ppout.quantity)`ï¼è¯¥ç产人å
³èæ¥å·¥ç**æ»äº§éä¹å**ï¼å¤äººæåæ¶æ¯æ»éï¼ï¼ |
| | | - ä¿®æ£ï¼`SUM(COALESCE(prp.quantity, slpa.finished_num))`ï¼å人æ¥å·¥æ¶è¾å
¥ç产éä¹åï¼æªæååéåå¼ï¼ã |
| | | |
| | | ```sql |
| | | -- ä¿®æ£ååå¼ |
| | | SUM(COALESCE(prp.quantity, slpa.finished_num)) AS output_num |
| | | ``` |
| | | |
| | | **ååºå段 `quantity`/`output_num` è¯ä¹ååï¼** ç±"æ¥å·¥æ»äº§é"æ¹ä¸º"该ç产人ç产é"ï¼åç«¯åæ¾ç¤ºæ éæ¹å¨ã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. data æ°æ®ï¼æ¥å·¥å¼¹çªï¼ |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | reportForm: { |
| | | workOrderId: null, |
| | | productProcessRouteItemId: null, |
| | | quantity: null, // äº§åºæ°é |
| | | addQty: 0, // å æ¾æ° |
| | | scrapQty: 0, // æ¥åºæ°é |
| | | }, |
| | | personList: [], // çç»äººåäº§éæ¶é¿æç» [{ userId, userName, quantity, workHour }] |
| | | teamList: [], // çç»ä¿¡æ¯ï¼åæï¼ |
| | | reportDialogVisible: false, |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 2. æ¥å·¥å¼¹çªæå¼æ¶åå§åçç»å½å
¥è¡ |
| | | |
| | | ```js |
| | | openReport(row) { |
| | | // row 为 getProductWorkOrderById è¿åçå·¥åæ°æ® |
| | | this.reportForm.workOrderId = row.id; |
| | | this.reportForm.productProcessRouteItemId = row.productProcessRouteItemId; |
| | | this.reportForm.quantity = null; |
| | | this.reportForm.addQty = row.processRouteAddNum ? Number(row.processRouteAddNum) : 0; |
| | | this.reportForm.scrapQty = 0; |
| | | // ç¨é»è®¤çç»æååå§åéè¡å½å
¥ï¼æ°é/æ¶é¿ééè¡å¡«åï¼ |
| | | this.personList = (row.reportPersons || []).map(p => ({ |
| | | userId: p.userId, |
| | | userName: p.userName, |
| | | quantity: null, |
| | | workHour: null, |
| | | })); |
| | | // teamList ä¹åæ¥ä¸ºé»è®¤æå |
| | | this.teamList = (row.reportPersons || []).map(p => ({ userId: p.userId, userName: p.userName })); |
| | | this.reportDialogVisible = true; |
| | | } |
| | | ``` |
| | | |
| | | ### 3. æ¥å·¥å¼¹çªéè¡å½å
¥äº§é/æ¶é¿è¡¨æ ¼ |
| | | |
| | | ```html |
| | | <el-table :data="personList" border> |
| | | <el-table-column label="ç产人" prop="userName" min-width="100" align="center" /> |
| | | <el-table-column label="产é" min-width="120" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-input-number v-model="scope.row.quantity" :min="0" :controls="false" placeholder="产é" style="width: 100%" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç产æ¶é¿(åé)" min-width="140" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-input-number v-model="scope.row.workHour" :min="0" :controls="false" placeholder="æ¶é¿(åé)" style="width: 100%" /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | ``` |
| | | |
| | | ### 4. æ¥å·¥æäº¤åæ°ï¼æºå¸¦ personListï¼ |
| | | |
| | | ```js |
| | | handleSubmit() { |
| | | // æ ¡éªåçç»äº§éä¹å = æ¥å·¥æ»äº§é |
| | | const total = this.personList.reduce((sum, p) => sum + (Number(p.quantity) || 0), 0); |
| | | if (Number(this.reportForm.quantity) !== total) { |
| | | this.$message.error('åçç»äº§éä¹åå¿
é¡»çäºæ¥å·¥æ»äº§é'); |
| | | return; |
| | | } |
| | | const params = { |
| | | workOrderId: this.reportForm.workOrderId, |
| | | productProcessRouteItemId: this.reportForm.productProcessRouteItemId, |
| | | quantity: this.reportForm.quantity, |
| | | addQty: this.reportForm.addQty, |
| | | scrapQty: this.reportForm.scrapQty, |
| | | teamList: this.teamList, |
| | | personList: this.personList, |
| | | deviceId: this.deviceId, |
| | | deviceName: this.deviceName, |
| | | startTime: this.startTime, |
| | | endTime: this.endTime, |
| | | }; |
| | | // è°ç¨ addProductMain ... |
| | | } |
| | | ``` |
| | | |
| | | ### 5. ç产æç»è¡¨æ°å¢äººåå·¥æ¶å |
| | | |
| | | ```html |
| | | <el-table-column prop="personWorkMinutes" label="人åå·¥æ¶(åé)" width="120" align="center" /> |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - `personList` æ¯äººç `quantity` ä¹åå¿
é¡»çäºæ¥å·¥æ»äº§é `quantity`ï¼å端æäº¤åéæ ¡éªï¼å端ä¹ä¼æ¦æªã |
| | | - `workHour` 为åéæ°ï¼ç±æä½å卿¥å·¥å¼¹çªæå¨å½å
¥ï¼åçç»åèªè®°å½ç产æ¶é¿ã |
| | | - å®¡æ ¸éè¿åï¼å端æ `personList` æ¯äººçæä¸æ¡çäº§æ ¸ç®è®°å½ï¼`sales_ledger_production_accounting`ï¼ï¼ |
| | | - `finished_num`ï¼å®ææ°éï¼= æ æ¥åºæ¶å个人产éï¼ææ¥åºæ¶æå人产éå æ¯åæåå¼ï¼äº§åº+å æ¾-æ¥åºï¼ï¼åèäºå
¥ä¿ç 2 ä½ã |
| | | - `work_hour` = 该人åå½å
¥çç产æ¶é¿ã |
| | | - å
¨é¨çç»çå·¥æ¶èªå¨æ±æ»å°çäº§æ ¸ç®ï¼è®¡ä»¶/计æ¶å·¥èµæäººç»è®¡ã |
| | | - å
¼å®¹æ§æ°æ®ï¼è¥æ¥å·¥æªä¼ `personList`ï¼å端åéä¸ºææºå°æä½åçææ ¸ç®ï¼`finished_num`=åå¼ï¼`work_hour`=æºå°ä¸æºæ¶é¿ï¼ï¼æ§æ¥å·¥ä¸åå½±åã |
| | | - å岿¥å·¥æ°æ® `production_report_person` 为空ï¼ç产æç»ä¸ `personWorkMinutes` åéå±ç¤ºæ¥å·¥æ¶é¿ `workMinutes`ã |
| | | - æ¯æåæ¹æ¥å·¥ï¼å®ææ°éæªè¾¾è®¡åæ°éæ¶å¯å¤æ¬¡æ¥å·¥ï¼æ¯æ¬¡æ¥å·¥ç¬ç«æ `personList` æ¯äººçæä¸æ¡æ ¸ç®ï¼ä¸å䏿ºè®°å½æ¥å·¥ç¶æéå¶ï¼å·¥åå®é
ç»ææ¶é´ä»
å¨å®ææ°éè¾¾å°è®¡åæ°éæ¶å¡«å
ãè¯¦è§ `docs/work_order_batch_report_fix.md`ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ç产工å带åºå æ¾æ° & æ¥å·¥æ ¸ç®ç»ä¸ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - ç产工åå表页ï¼`/productWorkOrder/page`ï¼ |
| | | - PDA æ¥å·¥å¼¹çªï¼æ°æ®æ¥æº `/productWorkOrder/getProductWorkOrderById`ï¼ |
| | | |
| | | ## API |
| | | |
| | | ### 1. ç产工åå页æ¥è¯¢ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /productWorkOrder/page | ç产工åå页æ¥è¯¢ï¼ååºæ°å¢å æ¾æ°å段 | |
| | | |
| | | **ååºæ°å¢å段ï¼ProductWorkOrderDtoï¼ï¼** |
| | | |
| | | | åæ° | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | processRouteAddNum | String | å æ¾æ°ï¼åèªå·¥èºè·¯çº¿é¡¹ç® `product_process_route_item.process_route_add_num`ï¼ | |
| | | |
| | | ### 2. PDA æ¥å·¥æ°æ®æ¥è¯¢ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /productWorkOrder/getProductWorkOrderById | æ¥å·¥å¼¹çªæ°æ®ï¼ååºæ°å¢å æ¾æ°å段ï¼ç¨ä½æ¥å·¥å¼¹çªå æ¾æ°é»è®¤å¼ï¼ | |
| | | |
| | | **ååºæ°å¢å段ï¼** |
| | | |
| | | | åæ° | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | processRouteAddNum | String | å æ¾æ° | |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. ç产工ååè¡¨è¡¨æ ¼å¢å å æ¾æ°å |
| | | |
| | | ```html |
| | | <el-table-column prop="processRouteAddNum" label="å æ¾æ°" width="100" align="center" /> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ®ï¼æ¥å·¥å¼¹çªè¡¨åï¼ |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | reportForm: { |
| | | quantity: null, // äº§åºæ°é |
| | | addQty: 0, // å æ¾æ°ï¼é»è®¤å¼ï¼å¯ä¿®æ¹ï¼ |
| | | scrapQty: 0, // æ¥åºæ°é |
| | | }, |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. æ¥å·¥å¼¹çªæå¼æ¶å¸¦åºå æ¾æ°é»è®¤å¼ |
| | | |
| | | ```js |
| | | openReport(row) { |
| | | // row 为 getProductWorkOrderById è¿åçå·¥åæ°æ® |
| | | this.reportForm.quantity = null; |
| | | this.reportForm.addQty = row.processRouteAddNum ? Number(row.processRouteAddNum) : 0; |
| | | this.reportForm.scrapQty = 0; |
| | | this.reportDialogVisible = true; |
| | | } |
| | | ``` |
| | | |
| | | ### 4. æ¥å·¥æäº¤åæ° |
| | | |
| | | è°ç¨ `POST /productionProductMain/addProductMain` æ¶ï¼è¯·æ±ä½éå
å«å æ¾æ°ï¼ |
| | | |
| | | ```js |
| | | const params = { |
| | | workOrderId: this.reportForm.workOrderId, |
| | | productProcessRouteItemId: this.reportForm.productProcessRouteItemId, |
| | | quantity: this.reportForm.quantity, // äº§åºæ°é |
| | | addQty: this.reportForm.addQty, // å æ¾æ° |
| | | scrapQty: this.reportForm.scrapQty, // æ¥åºæ°é |
| | | teamList: this.teamList, |
| | | deviceId: this.deviceId, |
| | | deviceName: this.deviceName, |
| | | startTime: this.startTime, |
| | | endTime: this.endTime, |
| | | }; |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - å æ¾æ° `processRouteAddNum` 为å符串类åï¼å端é `Number()` 转æ¢ååä½ä¸ºé»è®¤å¼å¡«å
¥ã |
| | | - æ¥å·¥æ°éæ ¸ç®å两个å£å¾ï¼ |
| | | - **å·¥åºæµè½¬ / æ»äº§é**ï¼ä¸æ£æ¥åºï¼ä¿æè¿è´¯ï¼ï¼å·¥å宿æ°éãç产订å宿æ°éãåå·¥åºæ»äº§éç»è®¡ãæ¯æ¥äº§åºç»è®¡ = **äº§åºæ°é + å æ¾æ°**ã |
| | | - **å®é
å
¥åº / è´¨æ£ / 计件工èµ**ï¼æ£æ¥åºï¼ï¼å
¥åºæ°éãè´¨æ£æ°éãçäº§æ ¸ç®ï¼è®¡ä»¶å·¥èµï¼ãæ¯æ¥å·¥èµç»è®¡ = **äº§åºæ°é + å æ¾æ° - æ¥åºæ°é**ã |
| | | - æ¥å·¥æ¥åºï¼scrapQtyï¼ä»
åæ°æ®è®°å½ï¼ä¸æ£åå·¥åºæµè½¬åºæ°ï¼åå·¥åºæ»äº§éä¿æè¿è´¯ã |
| | | - å岿¥å·¥æ°æ®è¥ `add_qty` 为空ï¼å端æ 0 å¤çï¼ä¸å½±åæ§æ°æ®æ ¸ç®ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æ°å¢éå®å°è´¦èªå¨å¼ç¥¨ãèªå¨å款 |
| | | |
| | | æ°å¢éå®å°è´¦ï¼é¡µé¢æ°å¢ãExcel 导å
¥ï¼æ¶ï¼å端èªå¨æååå
¨é¢çæå¼ç¥¨ç»è®°ä¸å款ç»è®°ï¼æ éå端ååç¬è°ç¨å¼ç¥¨ã忬¾æ¥å£ã |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - éå®å°è´¦åè¡¨é¡µï¼æ°å¢/ç¼è¾å¼¹çªã导å
¥ï¼ |
| | | - å¼ç¥¨ç»è®°é¡µé¢ |
| | | - 忬¾ç»è®°é¡µé¢ |
| | | - è´¢å¡ç®¡ç - æ¶å
¥ç®¡çé¡µé¢ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | /sales/ledger/addOrUpdateSalesLedger | æ°å¢/ä¿®æ¹éå®å°è´¦ï¼ä»
æ°å¢æ¶è§¦åèªå¨å¼ç¥¨ã忬¾ï¼ | |
| | | | POST | /sales/ledger/import | 导å
¥éå®å°è´¦ï¼æ¯æ¡å¯¼å
¥æåçå°è´¦å触åèªå¨å¼ç¥¨ã忬¾ï¼ | |
| | | |
| | | **请æ±åæ°ï¼** ä¸åæå®å
¨ä¸è´ï¼æ æ°å¢å段ã |
| | | |
| | | `/sales/ledger/addOrUpdateSalesLedger` 请æ±ç¤ºä¾ï¼ |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | å¦ | 为空=æ°å¢ï¼è§¦åèªå¨å¼ç¥¨å款ï¼ï¼é空=ä¿®æ¹ï¼ä¸è§¦åï¼ | |
| | | | customerId | Long | æ¯ | 客æ·ID | |
| | | | projectName | String | å¦ | 项ç®åç§° | |
| | | | entryDate | String | å¦ | å½å
¥æ¥æ yyyy-MM-dd | |
| | | | salesman | String | å¦ | ä¸å¡å | |
| | | | entryPerson | String | å¦ | å½å
¥äºº | |
| | | | type | Integer | æ¯ | å°è´¦ç±»å 1-éå® | |
| | | | productData | Array | æ¯ | 产åå表ï¼quantityãtaxInclusiveTotalPrice çï¼ååç»æï¼ | |
| | | | tempFileIds | Array | å¦ | 临æ¶éä»¶IDå表 | |
| | | |
| | | **ååºï¼** `{ "code": 200, "msg": "æä½æå" }`ï¼ç»æä¸åï¼ |
| | | |
| | | ## å端èªå¨çæçæ°æ®ï¼å端æ éè°ç¨æ¥å£ï¼ |
| | | |
| | | æ°å¢æååï¼å端å¨åä¸äºå¡å
èªå¨çæï¼ |
| | | |
| | | 1. å¼ç¥¨ç»è®°ï¼`invoice_registration` 主表 + æ¯ä¸ªäº§å䏿¡ `invoice_registration_product` + æ¯ä¸ªäº§å䏿¡ `invoice_ledger`ï¼ |
| | | - å¼ç¥¨æ° = äº§åæ°éï¼å¼ç¥¨éé¢ = 产åå«ç¨æ»ä»·ï¼å
¨é¢å¼ç¥¨ï¼ï¼ |
| | | - å票å·èªå¨çæï¼æ ¼å¼ `AUTO + æ¶é´æ³ + 产åID`ï¼å¦ `AUTO1755500000000123`ï¼ï¼ |
| | | - å¼ç¥¨æ¶é´ = å½å¤©ï¼å¼ç¥¨äºº = å½åç»å½äººã |
| | | 2. 忬¾ç»è®°ï¼æ¯ä¸ªäº§å䏿¡ `receipt_payment`ï¼ |
| | | - 忬¾éé¢ = å¼ç¥¨å
¨é¢ï¼åæ¬¾å½¢å¼ = 0ï¼çµæ±ï¼ï¼æ¥æ¬¾æ¥æ = å½å¤©ï¼ |
| | | - å·²å
³è对åºçå¼ç¥¨å°è´¦ `invoiceLedgerId`ã |
| | | 3. è´¢å¡æ¶å
¥ï¼æ¯æ¡å款对åºä¸æ¡ `account_income`ï¼æ¶å
¥ç±»å=忬¾æ¶å
¥ï¼ã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. æ°å¢å¼¹çªï¼æ éæ¹å¨è¯·æ±åæ° |
| | | |
| | | æ°å¢ä¿åæååï¼å»ºè®®æç¤ºè¯ä¸è¯´æå·²èªå¨å¼ç¥¨åæ¬¾ï¼ |
| | | |
| | | ```html |
| | | <el-button type="primary" @click="submitForm">ä¿ å</el-button> |
| | | ``` |
| | | |
| | | ```js |
| | | submitForm() { |
| | | addOrUpdateSalesLedger(this.form).then(res => { |
| | | if (res.code === 200) { |
| | | const msg = this.form.id ? 'ä¿®æ¹æå' : 'æ°å¢æåï¼å·²èªå¨å
¨é¢å¼ç¥¨å¹¶å
¨é¢å款'; |
| | | this.$modal.msgSuccess(msg); |
| | | this.open = false; |
| | | this.getList(); |
| | | } |
| | | }); |
| | | } |
| | | ``` |
| | | |
| | | ### 2. å表ç¼è¾æé®ï¼æ°å¢åé»è®¤ä¸å¯ç¼è¾ |
| | | |
| | | å端å表æ¥å£ `/sales/ledger/listPage` è¿åç `isEdit` è§åä¸åï¼åªè¦åå¨å¼ç¥¨æå款记å½å³ä¸º `false`ãç±äºæ°å¢å³èªå¨å¼ç¥¨åæ¬¾ï¼æ°å°è´¦ `isEdit` æä¸º `false`ï¼ç¼è¾æé®åºç¦ç¨ï¼ |
| | | |
| | | ```html |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | :disabled="scope.row.isEdit === false" |
| | | @click="handleUpdate(scope.row)" |
| | | >ä¿®æ¹</el-button> |
| | | ``` |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | // æ éæ°å¢åæ®µï¼æ²¿ç¨ scope.row.isEdit |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | å¦éä¿®æ¹å·²èªå¨å¼ç¥¨å款çå°è´¦ï¼è¯·èµ°ãå é¤ãåéæ°æ°å¢ï¼å é¤ä¼çº§èæ¸
çå¼ç¥¨ã忬¾åè´¢å¡æ¶å
¥è®°å½ï¼ã |
| | | |
| | | ### 3. å¼ç¥¨ç»è®° / 忬¾ç»è®°é¡µé¢ |
| | | |
| | | - å¼ç¥¨ç»è®°å表ä¼åºç°èªå¨çæçè®°å½ï¼å票å·å¸¦ `AUTO` åç¼ï¼å¯åå±ç¤ºåºåï¼ |
| | | - æ°å¢å°è´¦åï¼å¯¹åºäº§åçãæªå¼ç¥¨æ°/æªå¼ç¥¨éé¢ã为 0ï¼å¼ç¥¨ç»è®°å¼¹çªä¸è¯¥äº§åä¸å¯å次å¼ç¥¨ï¼åç«¯ä¼æ ¡éªè¶
éï¼ï¼ |
| | | - 忬¾ç»è®°é¡µé¢åçï¼èªå¨å款记å½å·²å
³èå票å·ã |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - ä»
`id` ä¸ºç©ºçæ°å¢ä¼è§¦åèªå¨å¼ç¥¨å款ï¼ä¿®æ¹å°è´¦ä¸ä¼è§¦åã |
| | | - èªå¨å¼ç¥¨å款ä»
é对 `type=1`ï¼éå®ï¼ç产åã |
| | | - äº§åæ°éæå«ç¨æ»ä»·ä¸ºç©º/为 0 æ¶è·³è¿è¯¥äº§åçèªå¨å¼ç¥¨å款ï¼ä¸é»æå°è´¦æ°å¢ã |
| | | - Excel 导å
¥ä¸é¡µé¢æ°å¢è¡ä¸ºä¸è´ï¼åèªå¨å¼ç¥¨å款ã |
| | | - å é¤éå®å°è´¦ä¼çº§èå é¤èªå¨çæçå¼ç¥¨ç»è®°ãå¼ç¥¨å°è´¦ã忬¾ç»è®°å对åºè´¢å¡æ¶å
¥è®°å½ã |
| | | - å°è´¦æ°å¢åå¦éè°æ´ï¼è¯·å é¤é建ï¼é¿å
ç´æ¥ä¿®æ¹å¯¼è´å¼ç¥¨/忬¾æ°æ®ä¸ä¸è´ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ç¨å°å®¡æ¹æ¥å
¥ååç»ä¸å®¡æ ¸ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - `src/views/collaborativeApproval/sealManagement/index.vue`ï¼ç¨å°ç®¡çï¼ç§»é¤é¡µé¢å
审æ¹ï¼ç³è¯·/éæ°ç³è¯·åèµ·åå审æ¹ï¼æ¯æéä»¶ä¸ä¼ ï¼ |
| | | - `src/api/collaborativeApproval/sealManagement.js`ï¼æ°å¢ `getSealDetail` æ¥å£ï¼ |
| | | - `src/views/collaborativeApproval/approvalProcess/index.vue`ï¼åå审æ¹ï¼æ°å¢"ç¨å°å®¡æ¹"页ç¾ï¼ |
| | | - `src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue`ï¼å®¡æ¹/详æ
å¼¹æ¡ï¼å±ç¤ºç¨å°è¯¦æ
ä¸éä»¶ï¼ |
| | | - `src/views/collaborativeApproval/approvalManagement/index.vue`ï¼å®¡æ¹ç®¡çï¼æ°å¢"ç¨å°å®¡æ¹"ç±»åé
ç½®ï¼ |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | /common/uploadsList | éç¨å¤æä»¶ä¸ä¼ ï¼æ¬å°ç£çï¼é minioï¼ï¼è¿åæä»¶å表 | |
| | | | POST | /sealApplicationManagement/add | æ°å¢/éæ°ç³è¯·ç¨å°ï¼åèµ· type=9 åå审æ¹ï¼ä¿åéä»¶ | |
| | | | GET | /sealApplicationManagement/detail | æå®¡æ¹æµç¨ id æ¥è¯¢ç¨å°ç³è¯·è¯¦æ
ï¼å«éä»¶ï¼ | |
| | | | GET | /sealApplicationManagement/getList | å页æ¥è¯¢ï¼æ¯æ¡è®°å½é带 commonFileList éä»¶ï¼ | |
| | | | POST | /approveProcess/exportNine | ç¨å°å®¡æ¹å¯¼åº | |
| | | |
| | | ### 1. ä¸ä¼ éä»¶ |
| | | |
| | | **POST /common/uploadsList** |
| | | |
| | | - 请æ±ï¼`multipart/form-data`ï¼å段å `files`ï¼å¯å¤ä¸ªï¼ |
| | | - ååºï¼ |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "æä½æå", |
| | | "data": [ |
| | | { "name": "åå§æä»¶å.pdf", "url": "http://host/profile/upload/xxx.pdf" } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | ### 2. æ°å¢/éæ°ç³è¯·ç¨å° |
| | | |
| | | **POST /sealApplicationManagement/add** |
| | | |
| | | 请æ±åæ°ï¼JSONï¼ï¼ |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | å¦ | å卿¶ä¸ºéæ°ç³è¯·ï¼å¤ç¨æ§åéæ°å起审æ¹ï¼ | |
| | | | applicationNum | String | æ¯ | ç³è¯·ç¼å· | |
| | | | title | String | æ¯ | ç³è¯·æ é¢ | |
| | | | sealType | String | æ¯ | ç¨å°ç±»åï¼official/contract/finance/legalï¼ | |
| | | | reason | String | æ¯ | ç³è¯·åå | |
| | | | urgency | String | å¦ | ç´§æ¥ç¨åº¦ï¼normal/urgent/very-urgentï¼ | |
| | | | deptId | Long | æ¯ | ç³è¯·é¨é¨ | |
| | | | attachmentList | Array | å¦ | éä»¶ `[{ name, url }]` | |
| | | |
| | | 说æï¼ |
| | | - æå¡ç«¯å¼ºå¶ `status = "pending"`ï¼èªå¨åå»ºå®¡æ¹æµç¨ï¼`approveType = 9`ï¼ï¼æµç¨å·åå `approve_process_id`ã |
| | | - éä»¶åå
¥ `common_file` 表ï¼`common_id` = å®¡æ¹æµç¨ DB 主é®ï¼`type` = 8 ApproveProcessï¼ã |
| | | - éæ°ç³è¯·æ¶ä¼å
æ¸
çæ§å®¡æ¹æµç¨å
³èçéä»¶ã |
| | | |
| | | ### 3. ç¨å°è¯¦æ
|
| | | |
| | | **GET /sealApplicationManagement/detail?approveProcessId=xxx** |
| | | |
| | | - 请æ±åæ°ï¼`approveProcessId`ï¼å®¡æ¹æµç¨ DB 主é®ï¼å³åå审æ¹å表记å½ç `id`ï¼ |
| | | - ååº data 为ç¨å°å对象ï¼å« `commonFileList` éä»¶å表ã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. ç¨å°ç®¡ç页ï¼sealManagement/index.vueï¼ |
| | | |
| | | - ç§»é¤å®¡æ¹äººéæ©ã审æ¹/æç»æä½æé®ï¼æä½åä»
ä¿ç"éæ°ç³è¯·"ï¼ç¶æä¸º rejected ä¸ä¸ºæ¬äººå建ï¼ä¸"详æ
"ã |
| | | - éä»¶ä¸ä¼ æ¹ä¸ºåç el-uploadï¼æå `/common/uploadsList`ï¼ |
| | | |
| | | ```html |
| | | <el-upload |
| | | multiple |
| | | :show-file-list="false" |
| | | :action="sealUploadUrl" |
| | | name="files" |
| | | :headers="uploadHeaders" |
| | | :limit="10" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | :on-exceed="handleUploadExceed" |
| | | > |
| | | <el-button type="primary">ç¹å»ä¸ä¼ éä»¶</el-button> |
| | | </el-upload> |
| | | ``` |
| | | |
| | | ```js |
| | | const sealUploadUrl = import.meta.env.VITE_APP_BASE_API + '/common/uploadsList' |
| | | const uploadHeaders = ref({ Authorization: 'Bearer ' + getToken() }) |
| | | const sealForm = reactive({ |
| | | id: null, applicationNum: '', title: '', sealType: '', |
| | | reason: '', urgency: 'normal', status: 'pending', attachmentList: [] |
| | | }) |
| | | // ä¸ä¼ æååè°ï¼æ {name, url} 追å è¿ attachmentList |
| | | const handleUploadSuccess = (res) => { |
| | | if (res.code === 200) { |
| | | const list = res.data || [] |
| | | list.forEach(item => sealForm.attachmentList.push({ name: item.name, url: item.url })) |
| | | ElMessage.success('ä¸ä¼ æå') |
| | | } else { |
| | | ElMessage.error(res.msg || 'ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - æäº¤ä¸éæ°ç³è¯·åè°ç¨ `addSealApplication(sealForm)`ï¼éæ°ç³è¯·é¢å¡« `attachmentList: row.commonFileList || []`ã |
| | | - é¢è§éä»¶å¿
é¡»ç¨å®æ´ URL ç´å¼ï¼`filePreviewRef.value.openUrl(url)`ï¼ä¸è¦ç¨ `open`ï¼ä¼åæ¼ hostï¼ã |
| | | - ä¸è½½éä»¶ä½¿ç¨ `<a>` éç¹æ¹å¼ï¼`download` æä»¶æ `byUrl` æ¹æ³ï¼ã |
| | | |
| | | ### 2. API å°è£
ï¼sealManagement.jsï¼ |
| | | |
| | | ```js |
| | | // ç¨å°ç³è¯·è¯¦æ
ï¼æå®¡æ¹æµç¨idï¼ |
| | | export function getSealDetail(approveProcessId) { |
| | | return request({ |
| | | url: "/sealApplicationManagement/detail", |
| | | method: "get", |
| | | params: { approveProcessId }, |
| | | }); |
| | | } |
| | | ``` |
| | | |
| | | ### 3. åå审æ¹é¡µï¼approvalProcess/index.vueï¼ |
| | | |
| | | - `approveTypes` æ°å¢ `{ value: '9', label: 'ç¨å°å®¡æ¹', icon: 'Stamp', color: '#7D3C98' }`ã |
| | | - ç±»å 9 éè"æ°å¢/å é¤"æé®ï¼`v-if` æ¡ä»¶è¿½å `&& currentApproveType !== 9`ï¼ã |
| | | - ç±»å 9 ç"ç¼è¾"æé® `disabled`ï¼ä¸ 5/6/7 ä¸è´ï¼ã |
| | | - ç±»å 9 ä¸å±ç¤º"éä»¶"æä½æé®ï¼éä»¶èµ° common_fileï¼ä¸èµ° storage_attachmentï¼ï¼ |
| | | |
| | | ```js |
| | | if (!isQuotationType && currentApproveType.value !== 9) { |
| | | actionOperations.push({ name: "éä»¶", /* ... */ }) |
| | | } |
| | | ``` |
| | | |
| | | - å¯¼åºæ å°è¿½å ï¼ |
| | | |
| | | ```js |
| | | const urlMap = { /* ... */ 9: "/approveProcess/exportNine" } |
| | | const nameMap = { /* ... */ 9: "ç¨å°å®¡æ¹è¡¨" } |
| | | ``` |
| | | |
| | | ### 4. 审æ¹å¼¹æ¡ï¼approvalDia.vueï¼ |
| | | |
| | | - æ°å¢ `isSealApproval = computed(() => Number(props.approveType) === 9)`ã |
| | | - ç¨å°å®¡æ¹æå¼å¼¹æ¡æ¶ï¼ç¨ `row.id`ï¼å®¡æ¹æµç¨ DB 主é®ï¼è¯·æ± `getSealDetail(row.id)`ï¼æ¸²æç¨å°è¯¦æ
+ éä»¶è¡¨æ ¼ï¼é¢è§/ä¸è½½ï¼ã |
| | | |
| | | ```js |
| | | if (isSealApproval.value) { |
| | | sealLoading.value = true |
| | | getSealDetail(row.id).then((res) => { |
| | | currentSeal.value = res.data || {} |
| | | }).catch((err) => { |
| | | proxy.$modal.msgError('æ¥è¯¢ç¨å°è¯¦æ
失败') |
| | | }).finally(() => { |
| | | sealLoading.value = false |
| | | }) |
| | | } |
| | | ``` |
| | | |
| | | - éä»¶é¢è§/ä¸è½½ä¸ç¨å°ç®¡ç页ä¸è´ï¼`openUrl` + éç¹ä¸è½½ï¼ã |
| | | |
| | | ### 5. 审æ¹ç®¡çé
置页ï¼approvalManagement/index.vueï¼ |
| | | |
| | | - `approveTypes`ã`approveTypeNameMap`ã`typeIconMap`ã`typeColorMap` å追å type 9ï¼label ç¨å°å®¡æ¹ï¼icon Stampï¼ã |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - éä»¶ä¸ä¼ ä¸å
è®¸ä½¿ç¨ minioï¼ç»ä¸èµ° `/common/uploadsList`ï¼æ¬å°ç£çåå¨ï¼ã |
| | | - ç¨å°åä¸å®¡æ¹æµç¨éè¿ `seal_application_management.approve_process_id`ï¼å®¡æ¹æµç¨ DB 主é®ï¼å
³èï¼åå审æ¹å表ä¸è¯¥è®°å½ç `id` å³å®¡æ¹æµç¨ DB 主é®ã |
| | | - ç¨å°å®¡æ¹ç±»åå¼ä¸º `approveType = 9`ï¼å®¡æ¹èç¹é
ç½®éå¨å®¡æ¹ç®¡ç-ç¨å°å®¡æ¹é¡µç¾ä¸é
ç½®ï¼DB åå§åèæ¬è§ `sql/seal_application_add_approve_process.sql`ï¼ã |
| | | - 审æ¹éè¿/驳ååï¼æå¡ç«¯ä¼åè°æ´æ°ç¨å°å `status`ï¼approved/rejected/pendingï¼ï¼å端åè¡¨å·æ°å³å¯çå°ææ°ç¶æã |
| | | - `filePreview.open(url)` ä¼å¨ URL åæ¼æ¥ `window.location.host`ï¼ä¼ å
¥å®æ´ URL æ¶å¿
é¡»ä½¿ç¨ `filePreview.openUrl(url)`ã |
| | | - å端 `download` æä»¶ä¸åå¨ `byUrl` æ¹æ³ï¼å®æ´ URL ä¸è½½è¯·ä½¿ç¨ `<a>` éç¹æ¹å¼ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # åºåæ±æ»åè¡¨è§æ ¼åå·æ¨¡ç³æ¥è¯¢ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - åºå管ç - åºåæ±æ»å表 |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | /stockInventory/pageListCombinedStockInventory | åºåæ±æ»å表æ¥è¯¢ï¼æ°å¢è§æ ¼åå·æ¨¡ç³æ¥è¯¢åæ° | |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | model | String | å¦ | è§æ ¼åå·ï¼æ¨¡ç³æ¥è¯¢ï¼å¹é
product_model.modelï¼ | |
| | | | productName | String | å¦ | 产ååç§°ï¼æ¨¡ç³æ¥è¯¢ | |
| | | | topParentProductId | Long | å¦ | é¡¶é¨ç¶äº§å id | |
| | | |
| | | **ååºï¼** ååºç»æä¸åï¼ä»ä¸º `StockInventoryDto` å页å表ï¼å
å« `model`ã`productName`ã`qualifiedQuantity`ã`unQualifiedQuantity` çåæ®µã |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. æç´¢æ¡ä»¶ |
| | | |
| | | å¨åºåæ±æ»å表页é¢çæç´¢è¡¨åä¸å¢å è§æ ¼åå·è¾å
¥æ¡ï¼ |
| | | |
| | | ```html |
| | | <el-form-item label="è§æ ¼åå·" prop="model"> |
| | | <el-input v-model="queryParams.model" placeholder="请è¾å
¥è§æ ¼åå·" clearable /> |
| | | </el-form-item> |
| | | ``` |
| | | |
| | | ### 2. data æ°æ® |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | productName: undefined, |
| | | model: undefined, |
| | | topParentProductId: undefined, |
| | | }, |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 3. æ¹æ³ |
| | | |
| | | ```js |
| | | /** æ¥è¯¢åºåæ±æ»å表 */ |
| | | function getList() { |
| | | loading.value = true |
| | | listStockInventory(queryParams.value).then(response => { |
| | | stockList.value = response.rows |
| | | total.value = response.total |
| | | loading.value = false |
| | | }) |
| | | } |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - `model` 为å¯éåæ°ï¼ä¸ä¼ æ¶è¿åå
¨é¨æ°æ®ï¼ä¸å½±ååææ¥è¯¢é»è¾ã |
| | | - è§æ ¼åå·æ¨¡ç³æ¥è¯¢åæ¶ä½ç¨äºåæ ¼åºåï¼stock_inventoryï¼åä¸åæ ¼åºåï¼stock_uninventoryï¼åå¹¶åçæ°æ®ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å·¥ååæ¹æ¥å·¥ä¿®å¤ |
| | | |
| | | ## é®é¢æè¿° |
| | | |
| | | æ¥å·¥ä¸æ¬¡åï¼å®ææ°éæªè¾¾è®¡åæ°éï¼ï¼ |
| | | 1. å·¥åãå®é
ç»ææ¶é´ã被èªå¨å¡«å
ï¼ |
| | | 2. å·¥åå表è¿å `hasUnreportedMachine=true`ï¼åç«¯ãæ¥å·¥ãæé®è¢«ç¦ç¨ï¼å¯¼è´æ æ³ç»§ç»åæ¹æ¥å·¥ç´è³å®æã |
| | | |
| | | ## ä¿®å¤å
容ï¼çº¯å端è¡ä¸º + å端ä¸è¡æ¹å¨ï¼æ æ°å¢/ä¿®æ¹æ¥å£ï¼ |
| | | |
| | | ### 1. å®é
ç»ææ¶é´ä»
å¨å®æåå¡«å
|
| | | |
| | | `ProductionProductMainServiceImpl.addProductMain`ï¼ |
| | | |
| | | - åé»è¾ï¼æ¯æ¬¡æ¥å·¥æ æ¡ä»¶è®¾ç½®å·¥å `actualEndTime` / `endProductTime` 为æ¥å·¥ç»ææ¶é´ï¼ |
| | | - ä¿®æ¹åï¼ä»
å½ `completeQuantity >= planQuantity` æ¶å¡«å
ï¼æªå®ææ¶æ¾å¼æ¸
空 `actualEndTime`/`endProductTime`ï¼èªæåå²èæ°æ®ï¼`updateById` é»è®¤å¿½ç¥ null åæ®µï¼æ
ç¨ `UpdateWrapper` æ¾å¼ç½®ç©ºï¼ã |
| | | |
| | | ### 2. åæ¹æ¥å·¥æ ¸ç®ææ¯æ¬¡æ¥å·¥ç¬ç«çæ |
| | | |
| | | `ProductionProductMainServiceImpl.nextAddProductMain`ï¼ |
| | | |
| | | - åé»è¾ï¼çäº§æ ¸ç®å¨ãæªæ¥å·¥ç䏿ºè®°å½ã循ç¯å
çæï¼ç¬¬ä¸æ¬¡æ¥å·¥å䏿ºè®°å½ `report_status=true`ï¼ç¬¬äºæ¬¡æ¥å·¥è¢« `continue` è·³è¿ï¼**ä¸ä¼çææ ¸ç®**ï¼ |
| | | - ä¿®æ¹åï¼æ¥å·¥ä¼ äºçç»äººåæç» `personList` æ¶ï¼**æ¯æ¬¡æ¥å·¥ç¬ç«æäººçæä¸æ¡æ ¸ç®**ï¼`finished_num` æå人æ¯äº§éå æ¯åæåå¼ï¼`work_hour` åå½å
¥æ¶é¿ï¼ï¼ä¸åå䏿ºè®°å½æ¥å·¥ç¶æå½±åï¼è®¾å¤åæ¥å·¥å `deviceId`ï¼æªå¡«åæ¶åéå该工åä»»ä¸å°æºã |
| | | - æªä¼ `personList`ï¼æ§æ°æ®ï¼æ¶ä»åéææªæ¥å·¥çæºå°ä¸æºæä½åçææ ¸ç®ï¼åé»è¾ä¿çã |
| | | |
| | | ### 3. å端æ¥å·¥æé®ä¸åå䏿ºè®°å½æ¥å·¥ç¶æéå¶ |
| | | |
| | | `src/views/productionManagement/workOrder/index.vue`ï¼ |
| | | |
| | | ```js |
| | | // ä¿®æ¹å |
| | | disabled: row => |
| | | row.completeQuantity >= row.planQuantity || |
| | | !canCurrentUserReport(row) || |
| | | row.hasUnreportedMachine, |
| | | |
| | | // ä¿®æ¹å |
| | | disabled: row => |
| | | row.completeQuantity >= row.planQuantity || |
| | | !canCurrentUserReport(row), |
| | | ``` |
| | | |
| | | ãæ¥å·¥ãæé®ä»
å¨ã宿æ°é >= è®¡åæ°éãæãå½åç¨æ·ä¸å¨å·¥å/å·¥åºæ¥å·¥äººä¸ãæ¶ç¦ç¨ï¼å
è®¸åæ¹æ¥å·¥ç´è³å®æã |
| | | |
| | | ## æ°æ®åºè¡ä¸ºéªè¯ |
| | | |
| | | 以工å `DC26081690001`ï¼è®¡å 16037ï¼ä¸ºä¾ï¼æ¥å·¥ 100 åï¼ |
| | | - `actual_end_time` ä¸åå¡«å
ï¼`completeQuantity=100 < 16037`ï¼ï¼ |
| | | - å·¥åå表 `has_unreported_machine` ä»ä¼è®¡ç®è¿åï¼å端已ä¸åç¨äºç¦ç¨æ¥å·¥æé®ï¼ï¼ |
| | | - ç»§ç»æ¥å·¥æ¶ï¼ç¬¬äºæ¬¡æ¥å·¥ä¹ä¼æ£å¸¸çæçäº§æ ¸ç®ã |
| | | |
| | | ## æ¶åæä»¶ |
| | | |
| | | - `src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java` |
| | | - `src/views/productionManagement/workOrder/index.vue` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æ¥å·¥çç»äººåäº§éæ¶é¿æç»è¡¨ |
| | | create table if not exists production_report_person |
| | | ( |
| | | id bigint auto_increment primary key, |
| | | product_main_id bigint not null comment 'æ¥å·¥ä¸»è¡¨id(production_product_main.id)', |
| | | user_id bigint not null comment 'ç产人id', |
| | | user_name varchar(50) null comment 'ç产人å§å', |
| | | quantity decimal(16,4) not null default 0 comment '该人åäº§åºæ°é', |
| | | work_hour int not null default 0 comment '该人åç产æ¶é¿(åé)', |
| | | tenant_id bigint null comment 'ç§æ·id', |
| | | create_time datetime null comment 'å建æ¶é´', |
| | | update_time datetime null comment 'æ´æ°æ¶é´', |
| | | create_user bigint null comment 'å建人', |
| | | update_user bigint null comment 'æ´æ°äºº', |
| | | dept_id bigint null comment 'é¨é¨id' |
| | | ) engine=innodb default charset=utf8mb4 comment='æ¥å·¥çç»äººåäº§éæ¶é¿æç»'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # è´¨éæ£éªè¡¨å¢å ç产工åidï¼ç¨äºæäº§ä¸è¾¾æ¶é¢çæç¬¬ä¸éå·¥åºè´¨æ£åï¼æ¤æ¶æ æ¥å·¥idï¼ |
| | | alter table quality_inspect |
| | | add column work_order_id bigint null comment 'ç产工åid(æäº§ä¸è¾¾é¢çæè´¨æ£åç¨)' after product_main_id; |
| | | |
| | | create index idx_quality_inspect_work_order_id on quality_inspect (work_order_id); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ç¨å°ç³è¯·ç®¡çæ¥å
¥ååç»ä¸å®¡æ ¸ |
| | | -- 使ç¨å确认å½åæ°æ®åºä¸ºä¸å¡åºï¼å¦ product-inventory-management-ygcyï¼ |
| | | |
| | | -- 1. ç¨å°ç³è¯·åå¢å å
³èååå®¡æ¹æµç¨idåæ®µ |
| | | ALTER TABLE seal_application_management |
| | | ADD COLUMN approve_process_id bigint DEFAULT NULL COMMENT 'å
³èååå®¡æ¹æµç¨id(approve_process.id)' AFTER approve_user_id; |
| | | |
| | | -- 2. å®¡æ¹æµç¨é
ç½®ï¼æ°å¢âç¨å°å®¡æ¹â(approve_type=9)审æ¹èç¹ |
| | | -- é»è®¤å®¡æ¹äººï¼ç¬¬ä¸çº§ 管çé¨(236)ï¼ç¬¬äºçº§ èµµæ¥å(214)ï¼å¯å¨ã审æ¹ç®¡çãèåè°æ´ |
| | | INSERT INTO approve_process_config_node (approve_type, node_order, approver_id, approver_name, timeout_hours, tenant_id, create_user, create_time, update_user, update_time, delete_flag, dept_id) |
| | | SELECT 9, 1, 236, '管çé¨', NULL, 1, 1, NOW(), 1, NOW(), 0, NULL FROM DUAL |
| | | WHERE NOT EXISTS (SELECT 1 FROM approve_process_config_node WHERE approve_type = 9 AND delete_flag = 0); |
| | | |
| | | INSERT INTO approve_process_config_node (approve_type, node_order, approver_id, approver_name, timeout_hours, tenant_id, create_user, create_time, update_user, update_time, delete_flag, dept_id) |
| | | SELECT 9, 2, 214, 'èµµæ¥å', NULL, 1, 1, NOW(), 1, NOW(), 0, NULL FROM DUAL |
| | | WHERE NOT EXISTS (SELECT 1 FROM approve_process_config_node WHERE approve_type = 9 AND node_order = 2 AND delete_flag = 0); |
| | |
| | | ExcelUtil<ApproveProcess> util = new ExcelUtil<ApproveProcess>(ApproveProcess.class); |
| | | util.exportExcel(response, accountExpenses, "å±é©ä½ä¸å®¡æ¹å¯¼åº"); |
| | | } |
| | | |
| | | @ApiOperation(value = "ç¨å°å®¡æ¹å¯¼åº") |
| | | @PostMapping("/exportNine") |
| | | public void exportNine(HttpServletResponse response) { |
| | | List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>() |
| | | .eq(ApproveProcess::getApproveDelete, 0) |
| | | .eq(ApproveProcess::getApproveType, 9)); |
| | | ExcelUtil<ApproveProcess> util = new ExcelUtil<ApproveProcess>(ApproveProcess.class); |
| | | util.exportExcel(response, accountExpenses, "ç¨å°å®¡æ¹å¯¼åº"); |
| | | } |
| | | } |
| | |
| | | private Integer approveNodeOrder; |
| | | |
| | | /** |
| | | * å®¡æ¹æ¨¡å¼ï¼or=æç¾ï¼and=ä¼ç¾ |
| | | */ |
| | | private String approveMode; |
| | | |
| | | /** |
| | | * 审æ¹èç¹ç¨æ·åå |
| | | */ |
| | | private String approveNodeUser; |
| | |
| | | private String approveUserCurrentName; |
| | | |
| | | /** |
| | | * å½åèç¹å¾
审人IDï¼éå·åéï¼æç¾/ä¼ç¾å¤äººï¼ |
| | | */ |
| | | private String approveUserCurrentIds; |
| | | |
| | | /** |
| | | * å½åèç¹å¾
审人å§åï¼éå·åéï¼ |
| | | */ |
| | | private String approveUserCurrentNames; |
| | | |
| | | /** |
| | | * èç¹ç»æå¿«ç
§JSONï¼[{nodeOrder,mode,userIds,userNames}]ï¼ç¨äºç¼è¾é建审æ¹èç¹ |
| | | */ |
| | | private String approveNodeConfig; |
| | | |
| | | /** |
| | | * ç³è¯·æ¥æ |
| | | */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | |
| | | @ApiModelProperty("èç¹é¡ºåº") |
| | | private Integer nodeOrder; |
| | | |
| | | /** |
| | | * å®¡æ¹æ¨¡å¼ï¼or=æç¾ï¼and=ä¼ç¾ |
| | | */ |
| | | @ApiModelProperty("å®¡æ¹æ¨¡å¼ï¼or=æç¾ï¼and=ä¼ç¾") |
| | | private String approveMode; |
| | | |
| | | |
| | | /** |
| | | * 审æ¹äººIDsï¼å¤ä¸ªç¨éå·åéï¼ |
| | |
| | | package com.ruoyi.approve.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo; |
| | | import com.ruoyi.approve.pojo.ApproveNode; |
| | | |
| | | import java.io.IOException; |
| | |
| | | public interface IApproveNodeService extends IService<ApproveNode> { |
| | | |
| | | void initApproveNodes(String approveUserIds,String approveID,Long tenantId); |
| | | |
| | | /** |
| | | * æé
ç½®èç¹å表åå§å审æ¹èç¹ï¼æ¯æåèç¹å¤å®¡æ¹äººä¸æç¾/ä¼ç¾æ¨¡å¼ï¼ |
| | | */ |
| | | void initApproveNodes(List<ApproveProcessConfigNodeVo> config, String approveID, Long tenantId); |
| | | /** |
| | | * 详æ
|
| | | * @param id |
| | |
| | | /** |
| | | * æ·»å å®¡æ¹æµç¨ |
| | | * @param approveProcessVO å®¡æ¹æµç¨VO对象 |
| | | * @return å®¡æ¹æµç¨ä¸»é®id |
| | | */ |
| | | void addApprove(ApproveProcessVO approveProcessVO) throws Exception; |
| | | Long addApprove(ApproveProcessVO approveProcessVO) throws Exception; |
| | | /** |
| | | * æ ¹æ®é¨é¨idæ¥è¯¢é¨é¨ä¿¡æ¯ |
| | | * @param deptIds é¨é¨IDæ°ç» |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo; |
| | | import com.ruoyi.approve.mapper.ApproveNodeMapper; |
| | | import com.ruoyi.approve.mapper.ApproveProcessMapper; |
| | | import com.ruoyi.approve.pojo.ApproveNode; |
| | | import com.ruoyi.approve.pojo.ApproveProcess; |
| | | import com.ruoyi.approve.service.IApproveNodeService; |
| | | import com.ruoyi.collaborativeApproval.mapper.SealApplicationManagementMapper; |
| | | import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | |
| | | |
| | | import java.io.IOException; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Arrays; |
| | | import java.util.ArrayList; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | @RequiredArgsConstructor |
| | |
| | | private final QualityTestStandardMapper qualityTestStandardMapper; |
| | | private final QualityTestStandardParamMapper qualityTestStandardParamMapper; |
| | | private final QualityInspectParamMapper qualityInspectParamMapper; |
| | | private final SealApplicationManagementMapper sealApplicationManagementMapper; |
| | | |
| | | |
| | | public ApproveProcess getApproveById(String id) { |
| | |
| | | |
| | | @Override |
| | | public void initApproveNodes(String approveUserIds, String approveID, Long tenantId) { |
| | | if (approveUserIds == null || approveUserIds.isEmpty()) { |
| | | return; |
| | | } |
| | | List<ApproveProcessConfigNodeVo> config = new ArrayList<>(); |
| | | String[] ids = approveUserIds.split(","); |
| | | for (int i = 0; i < ids.length; i++) { |
| | | if (ids[i] == null || ids[i].trim().isEmpty()) { |
| | | continue; |
| | | } |
| | | ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo(); |
| | | vo.setNodeOrder(i + 1); |
| | | vo.setApproverId(Long.parseLong(ids[i].trim())); |
| | | vo.setApproveMode("or"); |
| | | config.add(vo); |
| | | } |
| | | initApproveNodes(config, approveID, tenantId); |
| | | } |
| | | |
| | | @Override |
| | | public void initApproveNodes(List<ApproveProcessConfigNodeVo> config, String approveID, Long tenantId) { |
| | | Long userId = SecurityUtils.getLoginUser().getUser().getUserId(); |
| | | String[] names = approveUserIds.split(","); |
| | | for (int i = 0; i < names.length; i++) { |
| | | SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(names[i])); |
| | | if (sysUser == null) continue; |
| | | ApproveNode approveNode = new ApproveNode(); |
| | | approveNode.setApproveProcessId(approveID); |
| | | approveNode.setApproveNodeOrder(i + 1); |
| | | approveNode.setApproveNodeUser(sysUser.getNickName()); |
| | | approveNode.setApproveNodeUserId(sysUser.getUserId()); |
| | | approveNode.setApproveNodeTime(new Date()); |
| | | approveNode.setApproveNodeStatus(0); |
| | | approveNode.setTenantId(tenantId); |
| | | approveNode.setDeleteFlag(0); |
| | | approveNode.setCreateUser(userId); |
| | | approveNode.setUpdateUser(userId); |
| | | approveNode.setCreateTime(LocalDateTime.now()); |
| | | approveNode.setUpdateTime(LocalDateTime.now()); |
| | | approveNodeMapper.insert(approveNode); |
| | | // æèç¹é¡ºåºåç»ï¼ä¿è¯åä¸èç¹çå¤å®¡æ¹äººåå
¥ç¸å approveNodeOrder |
| | | Map<Integer, List<ApproveProcessConfigNodeVo>> groups = new LinkedHashMap<>(); |
| | | for (ApproveProcessConfigNodeVo vo : config) { |
| | | if (vo.getApproverId() == null) { |
| | | continue; |
| | | } |
| | | int order = vo.getNodeOrder() == null ? groups.size() + 1 : vo.getNodeOrder(); |
| | | groups.computeIfAbsent(order, k -> new ArrayList<>()).add(vo); |
| | | } |
| | | for (Map.Entry<Integer, List<ApproveProcessConfigNodeVo>> entry : groups.entrySet()) { |
| | | Integer order = entry.getKey(); |
| | | String mode = entry.getValue().get(0).getApproveMode(); |
| | | if (mode == null || mode.isEmpty()) { |
| | | mode = "or"; |
| | | } |
| | | List<Long> seenIds = new ArrayList<>(); |
| | | for (ApproveProcessConfigNodeVo vo : entry.getValue()) { |
| | | Long approverId = vo.getApproverId(); |
| | | if (seenIds.contains(approverId)) { |
| | | continue; |
| | | } |
| | | seenIds.add(approverId); |
| | | SysUser sysUser = sysUserMapper.selectUserById(approverId); |
| | | if (sysUser == null) { |
| | | continue; |
| | | } |
| | | ApproveNode approveNode = new ApproveNode(); |
| | | approveNode.setApproveProcessId(approveID); |
| | | approveNode.setApproveNodeOrder(order); |
| | | approveNode.setApproveMode(mode); |
| | | approveNode.setApproveNodeUser(sysUser.getNickName()); |
| | | approveNode.setApproveNodeUserId(sysUser.getUserId()); |
| | | approveNode.setApproveNodeTime(new Date()); |
| | | approveNode.setApproveNodeStatus(0); |
| | | approveNode.setTenantId(tenantId); |
| | | approveNode.setDeleteFlag(0); |
| | | approveNode.setCreateUser(userId); |
| | | approveNode.setUpdateUser(userId); |
| | | approveNode.setCreateTime(LocalDateTime.now()); |
| | | approveNode.setUpdateTime(LocalDateTime.now()); |
| | | approveNodeMapper.insert(approveNode); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | LambdaQueryWrapper<ApproveNode> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(ApproveNode::getApproveProcessId, id); |
| | | queryWrapper.eq(ApproveNode::getDeleteFlag, 0); |
| | | // queryWrapper.eq(ApproveNode::getApproveNodeStatus, 0); |
| | | List<ApproveNode> list = list(queryWrapper); |
| | | // æç
§ approveNodeOrder åæ®µååºæåº |
| | | list.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder)); |
| | | LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, id) |
| | | .eq(ApproveProcess::getApproveDelete, 0) |
| | | // .eq(ApproveProcess::getApproveStatus, 0) |
| | | .last("limit 1"); |
| | | ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper); |
| | | if (approveProcess != null && approveProcess.getApproveStatus() == 3) { |
| | | // æ approveNodeOrder ååºãåèç¹æ id ååºï¼ä¿è¯åèç¹å¤å®¡æ¹äººé¡ºåºç¨³å® |
| | | list.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder).thenComparingLong(ApproveNode::getId)); |
| | | bindNodeUrl(list); |
| | | ApproveProcess approveProcess = getApproveById(id); |
| | | if (approveProcess == null || approveProcess.getApproveStatus() == 2 |
| | | || approveProcess.getApproveStatus() == 3 || approveProcess.getApproveStatus() == 4) { |
| | | // æµç¨å·²å®æ/驳å/éæ°æäº¤ï¼å
¨é¨åªè¯» |
| | | return list; |
| | | } |
| | | Integer currentOrder = pendingOrder(id); |
| | | Long loginUserId = SecurityUtils.getLoginUser().getUser().getUserId(); |
| | | boolean admin = SecurityUtils.isAdmin(loginUserId); |
| | | boolean ishenSet = false; |
| | | for (ApproveNode approveNode : list) { |
| | | List<CommonFile> commonFiles = fileMapper.selectList(new LambdaQueryWrapper<CommonFile>() |
| | | .eq(CommonFile::getCommonId, approveNode.getId()) |
| | | .eq(CommonFile::getType, FileNameType.ApproveNode.getValue())); |
| | | if (!CollectionUtils.isEmpty(commonFiles)) { |
| | | approveNode.setUrl(commonFiles.get(0).getUrl()); |
| | | // 管çåä¸å审æ¹äººéå¶ï¼ä»£å®¡å½åèç¹é¦ä¸ªå¾
审记å½ï¼æ´èç¹ä»£å®¡ç± updateApproveNode å®æï¼ |
| | | if (approveNode.getApproveNodeOrder().equals(currentOrder) |
| | | && approveNode.getApproveNodeStatus() == 0 |
| | | && (admin || approveNode.getApproveNodeUserId().equals(loginUserId)) |
| | | && !ishenSet) { |
| | | approveNode.setIsShen(true); |
| | | ishenSet = true; |
| | | } |
| | | if (approveNode.getApproveNodeStatus() == 1) { |
| | | continue; |
| | | } |
| | | approveNode.setIsShen(true); |
| | | break; |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | public void updateApproveProcessStatus(ApproveNode approveNode, Integer status) throws IOException { |
| | | LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId()) |
| | | .eq(ApproveProcess::getApproveDelete, 0) |
| | | .last("limit 1"); |
| | | ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper); |
| | | if (approveProcess == null) throw new RuntimeException("审æ¹ä¸åå¨"); |
| | | LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveNode.getApproveProcessId()) |
| | | .eq(ApproveNode::getApproveNodeOrder, approveNode.getApproveNodeOrder() + 1) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | .eq(ApproveNode::getApproveNodeStatus, 0) |
| | | .last("limit 1"); |
| | | ApproveNode approveNode1 = approveNodeMapper.selectOne(approveNodeLambdaQueryWrapper); |
| | | approveProcess.setApproveStatus(status); |
| | | if (approveNode1 != null) { |
| | | approveProcess.setApproveUserCurrentId(approveNode1.getApproveNodeUserId()); |
| | | approveProcess.setApproveUserCurrentName(approveNode1.getApproveNodeUser()); |
| | | } |
| | | if (approveProcess.getApproveStatus().equals(2) || approveProcess.getApproveStatus().equals(3) || approveProcess.getApproveStatus().equals(4)) { |
| | | approveProcess.setApproveOverTime(new Date()); |
| | | } |
| | | approveProcessMapper.updateById(approveProcess); |
| | | |
| | | //éè´å®¡æ ¸ |
| | | if(approveProcess.getApproveType().equals(5)){ |
| | | /** |
| | | * ä¸å¡åè°ï¼æå®¡æ¹ç±»åæ´æ°å¯¹åºä¸å¡åæ®ç¶æ |
| | | * status: 1=å®¡æ ¸ä¸(ä¼ç¾é¨åéè¿), 2=å®¡æ ¸å®æ(åæ), 3=å®¡æ ¸æªéè¿(æç») |
| | | */ |
| | | private void applyBusinessStatus(ApproveProcess approveProcess, Integer status) { |
| | | // éè´å®¡æ¹ |
| | | if (approveProcess.getApproveType().equals(5)) { |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>() |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, approveProcess.getApproveReason()) |
| | | .last("limit 1")); |
| | | if(purchaseLedger != null) { |
| | | if (purchaseLedger != null) { |
| | | if (status.equals(2)) { |
| | | // åæ |
| | | // åæï¼çæè´¨æ£/å
¥åº |
| | | purchaseLedger.setApprovalStatus(3); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>() |
| | | .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2)); |
| | | for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) { |
| | | // è´¨æ£ |
| | | if (salesLedgerProduct.getIsChecked()) { |
| | | addQualityInspect(purchaseLedger, salesLedgerProduct); }else { |
| | | //ç´æ¥å
¥åº |
| | | stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId(),"-","-","-"); |
| | | addQualityInspect(purchaseLedger, salesLedgerProduct); |
| | | } else { |
| | | // ç´æ¥å
¥åº |
| | | stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId(), "-", "-", "-"); |
| | | } |
| | | } |
| | | } else if (status.equals(3)) { |
| | |
| | | } |
| | | } |
| | | // é宿¥ä»·ç¶æä¿®æ¹ |
| | | if(approveProcess.getApproveType().equals(6)){ |
| | | if (approveProcess.getApproveType().equals(6)) { |
| | | SalesQuotation salesQuote = salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>() |
| | | .eq(SalesQuotation::getQuotationNo, approveProcess.getApproveReason()) |
| | | .last("limit 1")); |
| | | // åæ |
| | | if(status.equals(2) && salesQuote != null){ |
| | | salesQuote.setStatus("éè¿"); |
| | | }else if(status.equals(3) && salesQuote != null){ |
| | | salesQuote.setStatus("æç»"); |
| | | }else if(status.equals(1) && salesQuote != null){ |
| | | salesQuote.setStatus("å®¡æ ¸ä¸"); |
| | | } |
| | | salesQuotationMapper.updateById(salesQuote); |
| | | } |
| | | // åºåºå®¡æ¹ä¿®æ¹ |
| | | if(approveProcess.getApproveType().equals(7)){ |
| | | String[] split = approveProcess.getApproveReason().split(":"); |
| | | ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>() |
| | | .eq(ShippingInfo::getShippingNo, split[1]) |
| | | .orderByDesc(ShippingInfo::getCreateTime) |
| | | .last("limit 1")); |
| | | if(shippingInfo != null){ |
| | | if(status.equals(2)){ |
| | | shippingInfo.setStatus("å®¡æ ¸éè¿"); |
| | | }else if(status.equals(3)){ |
| | | shippingInfo.setStatus("å®¡æ ¸æç»"); |
| | | }else if(status.equals(1)){ |
| | | shippingInfo.setStatus("å®¡æ ¸ä¸"); |
| | | if (salesQuote != null) { |
| | | if (status.equals(2)) { |
| | | salesQuote.setStatus("éè¿"); |
| | | } else if (status.equals(3)) { |
| | | salesQuote.setStatus("æç»"); |
| | | } else if (status.equals(1)) { |
| | | salesQuote.setStatus("å®¡æ ¸ä¸"); |
| | | } |
| | | shippingInfoMapper.updateById(shippingInfo); |
| | | salesQuotationMapper.updateById(salesQuote); |
| | | } |
| | | |
| | | } |
| | | // ç»å®éä»¶ |
| | | if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){ |
| | | tempFileService.migrateTempFilesToFormal(approveNode.getId(), approveNode.getTempFileIds(), FileNameType.ApproveNode.getValue()); |
| | | // åºåºå®¡æ¹ç¶æä¿®æ¹ |
| | | if (approveProcess.getApproveType().equals(7)) { |
| | | String[] split = approveProcess.getApproveReason().split(":"); |
| | | if (split.length > 1) { |
| | | ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>() |
| | | .eq(ShippingInfo::getShippingNo, split[1]) |
| | | .orderByDesc(ShippingInfo::getCreateTime) |
| | | .last("limit 1")); |
| | | if (shippingInfo != null) { |
| | | if (status.equals(2)) { |
| | | shippingInfo.setStatus("å®¡æ ¸éè¿"); |
| | | } else if (status.equals(3)) { |
| | | shippingInfo.setStatus("å®¡æ ¸æç»"); |
| | | } else if (status.equals(1)) { |
| | | shippingInfo.setStatus("å®¡æ ¸ä¸"); |
| | | } |
| | | shippingInfoMapper.updateById(shippingInfo); |
| | | } |
| | | } |
| | | } |
| | | // ç¨å°å®¡æ¹ç¶æä¿®æ¹ |
| | | if (approveProcess.getApproveType().equals(9)) { |
| | | SealApplicationManagement seal = sealApplicationManagementMapper.selectOne(new LambdaQueryWrapper<SealApplicationManagement>() |
| | | .eq(SealApplicationManagement::getApproveProcessId, approveProcess.getId()) |
| | | .last("limit 1")); |
| | | if (seal != null) { |
| | | if (status.equals(2)) { |
| | | seal.setStatus("approved"); |
| | | } else if (status.equals(3)) { |
| | | seal.setStatus("rejected"); |
| | | } else if (status.equals(1)) { |
| | | seal.setStatus("pending"); |
| | | } |
| | | sealApplicationManagementMapper.updateById(seal); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å½åå¾
审æ¹èç¹åºå·ï¼æææªå®¡æ¹èç¹ä¸æå°ç approveNodeOrder |
| | | */ |
| | | private Integer pendingOrder(String approveId) { |
| | | return list(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approveId) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | .eq(ApproveNode::getApproveNodeStatus, 0)) |
| | | .stream() |
| | | .map(ApproveNode::getApproveNodeOrder) |
| | | .min(Integer::compareTo) |
| | | .orElse(null); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æå®æµç¨æå®èç¹çå
¨é¨å®¡æ¹èç¹ï¼åèç¹å¤å®¡æ¹äººï¼æ id ååºï¼ |
| | | */ |
| | | private List<ApproveNode> nodesByOrder(String approveId, Integer order) { |
| | | return list(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approveId) |
| | | .eq(ApproveNode::getApproveNodeOrder, order) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | .orderByAsc(ApproveNode::getId)); |
| | | } |
| | | |
| | | /** |
| | | * 设置æµç¨å½åèç¹å¾
审人ï¼å¤å¼éå·åéï¼å
¼å®¹æ§çåå¼åæ®µï¼ |
| | | */ |
| | | private void setCurrentApprovers(ApproveProcess approveProcess, List<ApproveNode> nodes) { |
| | | if (nodes == null || nodes.isEmpty()) { |
| | | approveProcess.setApproveUserCurrentIds(null); |
| | | approveProcess.setApproveUserCurrentNames(null); |
| | | approveProcess.setApproveUserCurrentId(null); |
| | | approveProcess.setApproveUserCurrentName(null); |
| | | return; |
| | | } |
| | | approveProcess.setApproveUserCurrentIds(nodes.stream().map(ApproveNode::getApproveNodeUserId) |
| | | .map(String::valueOf).collect(Collectors.joining(","))); |
| | | approveProcess.setApproveUserCurrentNames(nodes.stream().map(ApproveNode::getApproveNodeUser) |
| | | .collect(Collectors.joining(","))); |
| | | approveProcess.setApproveUserCurrentId(nodes.get(0).getApproveNodeUserId()); |
| | | approveProcess.setApproveUserCurrentName(nodes.get(0).getApproveNodeUser()); |
| | | } |
| | | |
| | | /** |
| | | * éç¥å½åèç¹å
¨é¨å¾
审人 |
| | | */ |
| | | private void notifyApproveUsers(List<Long> userIds, ApproveProcess approveProcess) { |
| | | if (userIds == null || userIds.isEmpty()) { |
| | | return; |
| | | } |
| | | List<Long> ids = userIds.stream().distinct().collect(Collectors.toList()); |
| | | if (approveProcess.getApproveType() == 8) { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | ids, |
| | | "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | ids, |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¡«å
审æ¹èç¹éä»¶ url |
| | | */ |
| | | private void bindNodeUrl(List<ApproveNode> nodes) { |
| | | if (CollectionUtils.isEmpty(nodes)) { |
| | | return; |
| | | } |
| | | for (ApproveNode approveNode : nodes) { |
| | | List<CommonFile> commonFiles = fileMapper.selectList(new LambdaQueryWrapper<CommonFile>() |
| | | .eq(CommonFile::getCommonId, approveNode.getId()) |
| | | .eq(CommonFile::getType, FileNameType.ApproveNode.getValue())); |
| | | if (!CollectionUtils.isEmpty(commonFiles)) { |
| | | approveNode.setUrl(commonFiles.get(0).getUrl()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 临æ¶éä»¶è¿ç§»ä¸ºæ£å¼éä»¶ |
| | | */ |
| | | private void bindNodeFiles(ApproveNode approveNode, List<String> tempFileIds) throws IOException { |
| | | if (!CollectionUtils.isEmpty(tempFileIds) && approveNode.getApproveNodeStatus() != null |
| | | && approveNode.getApproveNodeStatus() == 1) { |
| | | tempFileService.migrateTempFilesToFormal(approveNode.getId(), tempFileIds, FileNameType.ApproveNode.getValue()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void updateApproveNode(ApproveNode approveNode) throws IOException { |
| | | // 审æ¹èç¹ç¶æ:1åæï¼2æç»ï¼0å°æªå®¡æ ¸ |
| | | switch (approveNode.getApproveNodeStatus()){ |
| | | case 1: |
| | | updateApproveProcessStatus(approveNode, Boolean.TRUE.equals(approveNode.getIsLast()) ? 2 : 1); |
| | | /*æ¶æ¯éç¥*/ |
| | | Integer nodeOrder = approveNode.getApproveNodeOrder(); |
| | | ApproveProcess approveProcess = approveProcessMapper.selectList(Wrappers.<ApproveProcess>lambdaQuery() |
| | | .eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())).get(0); |
| | | if (approveProcess.getApproveUserIds().split(",").length > nodeOrder){ |
| | | String id = approveProcess.getApproveUserIds().split(",")[nodeOrder]; |
| | | if (approveProcess.getApproveType()==8){ |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | }else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } |
| | | } |
| | | break; |
| | | case 2: |
| | | updateApproveProcessStatus(approveNode, 3); |
| | | break; |
| | | default: |
| | | break; |
| | | ApproveNode db = approveNodeMapper.selectById(approveNode.getId()); |
| | | if (db == null || db.getDeleteFlag() != null && db.getDeleteFlag() == 1) { |
| | | throw new RuntimeException("审æ¹èç¹ä¸åå¨"); |
| | | } |
| | | approveNode.setApproveNodeTime(new Date()); |
| | | approveNodeMapper.updateById(approveNode); |
| | | if (db.getApproveNodeStatus() != null && db.getApproveNodeStatus() != 0) { |
| | | throw new RuntimeException("该èç¹å·²å®¡æ¹ï¼è¯·å¿é夿ä½"); |
| | | } |
| | | Long loginUserId = SecurityUtils.getLoginUser().getUser().getUserId(); |
| | | boolean admin = SecurityUtils.isAdmin(loginUserId); |
| | | // 管çåä¸å审æ¹äººéå¶ |
| | | if (!admin && !db.getApproveNodeUserId().equals(loginUserId)) { |
| | | throw new RuntimeException("æ æå®¡æ¹è¯¥èç¹"); |
| | | } |
| | | ApproveProcess approveProcess = getApproveById(db.getApproveProcessId()); |
| | | if (approveProcess == null) { |
| | | throw new RuntimeException("å®¡æ¹æµç¨ä¸åå¨"); |
| | | } |
| | | if (approveProcess.getApproveStatus() == null |
| | | || (approveProcess.getApproveStatus() != 0 && approveProcess.getApproveStatus() != 1)) { |
| | | throw new RuntimeException("å½åæµç¨ç¶æä¸å
许审æ¹"); |
| | | } |
| | | Integer curOrder = pendingOrder(db.getApproveProcessId()); |
| | | if (!db.getApproveNodeOrder().equals(curOrder)) { |
| | | throw new RuntimeException("å°æªè½®å°è¯¥èç¹å®¡æ¹"); |
| | | } |
| | | |
| | | db.setApproveNodeStatus(approveNode.getApproveNodeStatus()); |
| | | db.setApproveNodeReason(approveNode.getApproveNodeReason()); |
| | | db.setApproveNodeRemark(approveNode.getApproveNodeRemark()); |
| | | db.setApproveNodeTime(new Date()); |
| | | db.setUpdateUser(loginUserId); |
| | | approveNodeMapper.updateById(db); |
| | | |
| | | // æç»ï¼ä¸ç¥¨å¦å³ï¼ç«å³é©³åæ´ä¸ªæµç¨ |
| | | if (db.getApproveNodeStatus() != null && db.getApproveNodeStatus() == 2) { |
| | | approveProcess.setApproveStatus(3); |
| | | approveProcess.setApproveOverTime(new Date()); |
| | | approveProcessMapper.updateById(approveProcess); |
| | | applyBusinessStatus(approveProcess, 3); |
| | | bindNodeFiles(db, approveNode.getTempFileIds()); |
| | | return; |
| | | } |
| | | |
| | | String mode = db.getApproveMode(); |
| | | if (mode == null || mode.isEmpty()) { |
| | | mode = "or"; |
| | | } |
| | | List<ApproveNode> sameOrder = nodesByOrder(db.getApproveProcessId(), db.getApproveNodeOrder()); |
| | | // 管çå代审ï¼å½åèç¹å
¶ä½å¾
审记å½ä¸å¹¶éè¿ |
| | | if (admin) { |
| | | for (ApproveNode n : sameOrder) { |
| | | if (n.getApproveNodeStatus() == null || n.getApproveNodeStatus() == 0) { |
| | | n.setApproveNodeStatus(1); |
| | | n.setApproveNodeRemark("管çå代审éè¿"); |
| | | n.setApproveNodeTime(new Date()); |
| | | approveNodeMapper.updateById(n); |
| | | } |
| | | } |
| | | } |
| | | boolean released; |
| | | if ("and".equals(mode)) { |
| | | // ä¼ç¾ï¼èç¹å
ææäººååæææ¾è¡ |
| | | released = sameOrder.stream().allMatch(n -> n.getApproveNodeStatus() != null && n.getApproveNodeStatus() == 1); |
| | | } else { |
| | | // æç¾ï¼èç¹å
ä»»ä¸åæå³æ¾è¡ |
| | | released = sameOrder.stream().anyMatch(n -> n.getApproveNodeStatus() != null && n.getApproveNodeStatus() == 1); |
| | | } |
| | | |
| | | // ä¼ç¾æªæ¾è¡ï¼èç¹å
仿å¾
å®¡äººï¼æµç¨ä¿æå®¡æ ¸ä¸ |
| | | if (!released) { |
| | | List<ApproveNode> pending = sameOrder.stream() |
| | | .filter(n -> n.getApproveNodeStatus() == null || n.getApproveNodeStatus() == 0) |
| | | .collect(Collectors.toList()); |
| | | approveProcess.setApproveStatus(1); |
| | | setCurrentApprovers(approveProcess, pending); |
| | | approveProcessMapper.updateById(approveProcess); |
| | | applyBusinessStatus(approveProcess, 1); |
| | | bindNodeFiles(db, approveNode.getTempFileIds()); |
| | | return; |
| | | } |
| | | |
| | | // æç¾æ¾è¡ï¼åèç¹å
¶ä½æªå®¡æ¹è®°å½æ 记为èªå¨åæ |
| | | if (!"and".equals(mode)) { |
| | | for (ApproveNode n : sameOrder) { |
| | | if (n.getApproveNodeStatus() == null || n.getApproveNodeStatus() == 0) { |
| | | n.setApproveNodeStatus(1); |
| | | n.setApproveNodeRemark("æç¾ï¼å
¶ä»å®¡æ¹äººå·²éè¿"); |
| | | n.setApproveNodeTime(new Date()); |
| | | approveNodeMapper.updateById(n); |
| | | } |
| | | } |
| | | } |
| | | |
| | | List<ApproveNode> next = nodesByOrder(db.getApproveProcessId(), db.getApproveNodeOrder() + 1).stream() |
| | | .filter(n -> n.getApproveNodeStatus() == null || n.getApproveNodeStatus() == 0) |
| | | .collect(Collectors.toList()); |
| | | if (next.isEmpty()) { |
| | | // æåèç¹æ¾è¡ï¼æµç¨å®æ |
| | | approveProcess.setApproveStatus(2); |
| | | approveProcess.setApproveOverTime(new Date()); |
| | | setCurrentApprovers(approveProcess, new ArrayList<>()); |
| | | approveProcessMapper.updateById(approveProcess); |
| | | applyBusinessStatus(approveProcess, 2); |
| | | } else { |
| | | // æµè½¬ä¸ä¸èç¹ |
| | | approveProcess.setApproveStatus(1); |
| | | setCurrentApprovers(approveProcess, next); |
| | | approveProcessMapper.updateById(approveProcess); |
| | | applyBusinessStatus(approveProcess, 1); |
| | | notifyApproveUsers(next.stream().map(ApproveNode::getApproveNodeUserId).collect(Collectors.toList()), approveProcess); |
| | | } |
| | | bindNodeFiles(db, approveNode.getTempFileIds()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | return "å货审æ¹"; |
| | | case 8: |
| | | return "å±é©ä½ä¸å®¡æ¹"; |
| | | case 9: |
| | | return "ç¨å°å®¡æ¹"; |
| | | } |
| | | return null; |
| | | } |
| | |
| | | private final ApproveProcessConfigNodeMapper approveProcessConfigNodeMapper; |
| | | @Override |
| | | public List<ApproveProcessConfigNodeVo> listNode(Integer type) { |
| | | List<ApproveProcessConfigNode> approveProcessConfigNodes = approveProcessConfigNodeMapper.selectList(new QueryWrapper<ApproveProcessConfigNode>().lambda().eq(ApproveProcessConfigNode::getApproveType, type).orderByAsc(ApproveProcessConfigNode::getNodeOrder)); |
| | | List<ApproveProcessConfigNode> approveProcessConfigNodes = approveProcessConfigNodeMapper.selectList(new QueryWrapper<ApproveProcessConfigNode>().lambda() |
| | | .eq(ApproveProcessConfigNode::getApproveType, type) |
| | | .orderByAsc(ApproveProcessConfigNode::getNodeOrder) |
| | | .orderByAsc(ApproveProcessConfigNode::getId)); |
| | | return approveProcessConfigNodes.stream() |
| | | .map(node -> { |
| | | ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo(); |
| | |
| | | approveProcessConfigNodeMapper.delete(new QueryWrapper<ApproveProcessConfigNode>().lambda().eq(ApproveProcessConfigNode::getApproveType, approveProcessConfigNodes.get(0).getApproveType())); |
| | | //æ°å¢ æ°æ® |
| | | for (ApproveProcessConfigNode node : approveProcessConfigNodes) { |
| | | // é»è®¤æç¾æ¨¡å¼ï¼å
¼å®¹æªä¼ approve_mode çæ§æ°æ® |
| | | if (node.getApproveMode() == null || node.getApproveMode().isEmpty()) { |
| | | node.setApproveMode("or"); |
| | | } |
| | | approveProcessConfigNodeMapper.insert(node); |
| | | } |
| | | return true; |
| | |
| | | import com.ruoyi.approve.service.ApproveProcessConfigNodeService; |
| | | import com.ruoyi.approve.service.IApproveNodeService; |
| | | import com.ruoyi.approve.service.IApproveProcessService; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | |
| | | @RequiredArgsConstructor |
| | | public class ApproveProcessServiceImpl extends ServiceImpl<ApproveProcessMapper, ApproveProcess> implements IApproveProcessService { |
| | | private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd"); |
| | | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); |
| | | |
| | | private final SysDeptMapper sysDeptMapper; |
| | | private final IApproveNodeService approveNodeService; |
| | |
| | | private final ApproveProcessConfigNodeService approveProcessConfigNodeService; |
| | | |
| | | @Override |
| | | public void addApprove(ApproveProcessVO approveProcessVO) throws Exception { |
| | | public Long addApprove(ApproveProcessVO approveProcessVO) throws Exception { |
| | | SysUser sysUser = SecurityUtils.getLoginUser().getUser(); |
| | | SysDept sysDept = sysDeptMapper.selectDeptById(SecurityUtils.getLoginUser().getCurrentDeptId()); |
| | | List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode( approveProcessVO.getApproveType()); |
| | | List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode(approveProcessVO.getApproveType()); |
| | | // æèç¹é¡ºåºåç»ï¼åèç¹å¤å®¡æ¹äººï¼ |
| | | List<List<ApproveProcessConfigNodeVo>> groups = groupByOrder(list); |
| | | if (groups.isEmpty()) throw new RuntimeException("æ·»å 审æ¹èç¹å人å"); |
| | | List<ApproveProcessConfigNodeVo> firstGroup = groups.get(0); |
| | | List<Long> nodeIds = list.stream() |
| | | .map(ApproveProcessConfigNodeVo::getApproverId) |
| | | .collect(Collectors.toList()); |
| | |
| | | approveProcess.setApproveType(approveProcessVO.getApproveType()); |
| | | approveProcess.setCreateTime(LocalDateTime.now()); |
| | | approveProcess.setTenantId(approveProcessVO.getApproveDeptId()); |
| | | approveProcess.setApproveUserCurrentId(nodeIds.get(0)); |
| | | approveProcess.setApproveUserCurrentName(sysUsers |
| | | .stream() |
| | | .filter(SysUser -> SysUser.getUserId().equals(nodeIds.get(0))) |
| | | .collect(Collectors.toList()) |
| | | .get(0) |
| | | .getNickName()); |
| | | setFirstNodeApprovers(approveProcess, firstGroup, sysUsers); |
| | | // è®¾ç½®ç¶æä¸ºéæ°æäº¤ |
| | | if (approveProcessVO.getId() != null) { |
| | | ApproveProcess approveProcess1 = approveProcessMapper.selectById(approveProcessVO.getId()); |
| | | approveProcess1.setApproveStatus(4); |
| | | approveProcessMapper.updateById(approveProcess1); |
| | | } |
| | | // èç¹ç»æå¿«ç
§ï¼ä¾ç¼è¾é建审æ¹èç¹æ¶ä¿åç»ä¸æ¨¡å¼ï¼ |
| | | approveProcess.setApproveNodeConfig(buildNodeConfig(list)); |
| | | save(approveProcess); |
| | | //åå§å审æ¹èç¹ |
| | | String nodeIdStr = nodeIds.stream() |
| | | .map(String::valueOf) |
| | | .collect(Collectors.joining(",")); |
| | | approveNodeService.initApproveNodes(nodeIdStr, no, approveProcessVO.getApproveDeptId()); |
| | | //åå§å审æ¹èç¹ï¼æé
ç½®èç¹åç»ï¼æ¯æåèç¹å¤å®¡æ¹äºº/æç¾ä¼ç¾ï¼ |
| | | approveNodeService.initApproveNodes(list, no, approveProcessVO.getApproveDeptId()); |
| | | // éä»¶ç»å® |
| | | tempFileService.migrateTempFilesToFormal(approveProcess.getId(), approveProcessVO.getTempFileIds(), FileNameType.ApproveProcess.getValue()); |
| | | /*æ¶æ¯éç¥*/ |
| | | Long id = nodeIds.get(0); |
| | | if (approveProcess.getApproveType()==8){ |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Collections.singletonList(id), |
| | | "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | }else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Collections.singletonList(id), |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } |
| | | /*æ¶æ¯éç¥ï¼éç¥ç¬¬ä¸èç¹å
¨é¨å®¡æ¹äººï¼*/ |
| | | notifyApproveUsers(approveProcess, firstGroupUserIds(approveProcess)); |
| | | return approveProcess.getId(); |
| | | } |
| | | |
| | | @Override |
| | |
| | | .last("limit 1"); |
| | | ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper); |
| | | if (approveProcess == null) throw new RuntimeException("è¯·éæ©å®¡æ¹äºº"); |
| | | String[] split = approveGetAndUpdateVo.getApproveUserIds().split(","); |
| | | if (split.length == 0) { |
| | | String newIds = approveGetAndUpdateVo.getApproveUserIds(); |
| | | if (newIds == null || newIds.trim().isEmpty()) { |
| | | throw new RuntimeException("è¯·éæ©å®¡æ¹äºº"); |
| | | } |
| | | List<SysUser> sysUsers = sysUserMapper.selectUserByIds(Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList())); |
| | | List<Long> newIdList = parseUserIds(newIds); |
| | | List<SysUser> sysUsers = sysUserMapper.selectUserByIds(newIdList); |
| | | if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("è¯·éæ©å®¡æ¹äºº"); |
| | | //å®¡æ ¸ä¸ä¸å¯ä»¥ç¼è¾å®¡æ ¸äºº |
| | | if (approveProcess.getApproveStatus() != 1) { |
| | | approveProcess.setApproveUserCurrentId(Long.parseLong(split[0])); |
| | | approveProcess.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[0]))).collect(Collectors.toList()).get(0).getNickName()); |
| | | } |
| | | approveProcess.setApproveUserIds(newIds); |
| | | approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(","))); |
| | | if (approveGetAndUpdateVo.getApproveStatus() != null) { |
| | | approveProcess.setApproveStatus(approveGetAndUpdateVo.getApproveStatus()); |
| | | } |
| | | approveProcess.setApproveUserIds(approveGetAndUpdateVo.getApproveUserIds()); |
| | | updateById(approveProcess); |
| | | //ä¿®æ¹å®¡æ¹äºº |
| | | // å
å é¤ åæ°å¢ |
| | | LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId()) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | // .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId()) |
| | | .orderByAsc(ApproveNode::getApproveNodeOrder); |
| | | approveNodeMapper.delete(approveNodeLambdaQueryWrapper); |
| | | approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approveProcess.getApproveId(), approveProcess.getTenantId()); |
| | | /*æ¶æ¯éç¥*/ |
| | | String id = approveProcess.getApproveUserIds().split(",")[0]; |
| | | if (approveProcess.getApproveType()==8){ |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | }else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | // å
å é¤ åæ°å¢ï¼ä¼å
æ approve_node_config å¿«ç
§ä¿åç»ä¸æ¨¡å¼ï¼ |
| | | approveNodeMapper.delete(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId()) |
| | | .eq(ApproveNode::getDeleteFlag, 0)); |
| | | rebuildApproveNodes(approveProcess, newIds); |
| | | // å®¡æ ¸ä¸ä¸å¯ä»¥ç¼è¾å®¡æ ¸äºº |
| | | if (approveProcess.getApproveStatus() != 1) { |
| | | refreshCurrentApprovers(approveProcess); |
| | | } else { |
| | | approveProcessMapper.updateById(approveProcess); |
| | | } |
| | | /*æ¶æ¯éç¥ï¼éç¥ç¬¬ä¸èç¹å
¨é¨å®¡æ¹äººï¼*/ |
| | | notifyApproveUsers(approveProcess, firstGroupUserIds(approveProcess)); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void updateByApproveId(ApproveGetAndUpdateVo approveGetAndUpdateVo) throws IOException { |
| | | ApproveProcess approve = approveProcessMapper.selectById(approveGetAndUpdateVo.getId()); |
| | | Integer oldStatus = approve.getApproveStatus(); |
| | | BeanUtils.copyProperties(approveGetAndUpdateVo, approve); |
| | | approve.setApproveUserIds(approveGetAndUpdateVo.getApproveUserIds()); |
| | | // BeanUtils 伿·è´ nullï¼é²æ¢æå®¡æ¹ç¶æè¦ç为空 |
| | | if (approveGetAndUpdateVo.getApproveStatus() == null) { |
| | | approve.setApproveStatus(oldStatus); |
| | | } |
| | | approve.setApproveReason(approveGetAndUpdateVo.getApproveReason()); |
| | | SysUser sysUser = sysUserMapper.selectUserById(approveGetAndUpdateVo.getApproveUser()); |
| | | String[] split = approveGetAndUpdateVo.getApproveUserIds().split(","); |
| | | if (split.length == 0) { |
| | | String newIds = approveGetAndUpdateVo.getApproveUserIds(); |
| | | if (newIds == null || newIds.trim().isEmpty()) { |
| | | throw new RuntimeException("è¯·éæ©å®¡æ¹äºº"); |
| | | } |
| | | List<SysUser> sysUsers = sysUserMapper.selectUserByIds(Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList())); |
| | | List<Long> newIdList = parseUserIds(newIds); |
| | | List<SysUser> sysUsers = sysUserMapper.selectUserByIds(newIdList); |
| | | if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("è¯·éæ©å®¡æ¹äºº"); |
| | | SysUser sysUser = sysUserMapper.selectUserById(approveGetAndUpdateVo.getApproveUser()); |
| | | if (sysUser == null) throw new RuntimeException("ç³è¯·äººä¸åå¨"); |
| | | approve.setApproveUserName(sysUser.getNickName()); |
| | | approve.setApproveUser(sysUser.getUserId()); |
| | | //å®¡æ ¸ä¸ä¸å¯ä»¥ç¼è¾å®¡æ ¸äºº |
| | | approve.setApproveUserIds(newIds); |
| | | approve.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(","))); |
| | | //ä¿®æ¹å®¡æ¹äººï¼å
å é¤åæ°å¢ï¼ä¼å
æ approve_node_config å¿«ç
§ä¿åç»ä¸æ¨¡å¼ï¼ |
| | | approveNodeMapper.delete(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approve.getApproveId()) |
| | | .eq(ApproveNode::getDeleteFlag, 0)); |
| | | rebuildApproveNodes(approve, newIds); |
| | | // å®¡æ ¸ä¸ä¸å¯ä»¥ç¼è¾å®¡æ ¸äºº |
| | | if (approve.getApproveStatus() != 1) { |
| | | approve.setApproveUserCurrentId(Long.parseLong(split[0])); |
| | | approve.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[0]))).collect(Collectors.toList()).get(0).getNickName()); |
| | | refreshCurrentApprovers(approve); |
| | | } else { |
| | | approveProcessMapper.updateById(approve); |
| | | } |
| | | updateById(approve); |
| | | //ä¿®æ¹å®¡æ¹äºº |
| | | // å
å é¤ åæ°å¢ |
| | | LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approve.getApproveId()) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | // .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId()) |
| | | .orderByAsc(ApproveNode::getApproveNodeOrder); |
| | | approveNodeMapper.delete(approveNodeLambdaQueryWrapper); |
| | | approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approve.getApproveId(), approve.getTenantId()); |
| | | |
| | | // int i = 0; |
| | | // for (ApproveNode approveNode : list) { |
| | | // int finalI = i; |
| | | // if(i >= split.length){ |
| | | // approveNode.setDeleteFlag(1); |
| | | // }else{ |
| | | // List<SysUser> collect = sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[finalI]))).collect(Collectors.toList()); |
| | | // if(CollectionUtils.isEmpty(collect)){ |
| | | // throw new RuntimeException("è¯·éæ©æ£ç¡®ç审æ¹äºº"); |
| | | // } |
| | | // approveNode.setApproveNodeUserId(collect.get(0).getUserId()); |
| | | // approveNode.setApproveNodeUser(collect.get(0).getNickName()); |
| | | // } |
| | | // approveNodeMapper.updateById(approveNode); |
| | | // i++; |
| | | // } |
| | | tempFileService.migrateTempFilesToFormal(approve.getId(), approveGetAndUpdateVo.getTempFileIds(), FileNameType.ApproveProcess.getValue()); |
| | | /*æ¶æ¯éç¥*/ |
| | | String id = approve.getApproveUserIds().split(",")[0]; |
| | | if (approve.getApproveType()==8){ |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()), |
| | | approve.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/safeProduction/safeWorkApproval?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId()); |
| | | }else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()), |
| | | approve.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | Arrays.asList(Long.valueOf(id)), |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId()); |
| | | } |
| | | |
| | | /*æ¶æ¯éç¥ï¼éç¥ç¬¬ä¸èç¹å
¨é¨å®¡æ¹äººï¼*/ |
| | | notifyApproveUsers(approve, firstGroupUserIds(approve)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * æèç¹é¡ºåºåç»ï¼ä¿åºï¼ï¼åèç¹å¤å®¡æ¹äººå½å
¥ä¸ç» |
| | | */ |
| | | private List<List<ApproveProcessConfigNodeVo>> groupByOrder(List<ApproveProcessConfigNodeVo> list) { |
| | | Map<Integer, List<ApproveProcessConfigNodeVo>> map = new LinkedHashMap<>(); |
| | | for (ApproveProcessConfigNodeVo vo : list) { |
| | | if (vo.getApproverId() == null) { |
| | | continue; |
| | | } |
| | | int order = vo.getNodeOrder() == null ? map.size() + 1 : vo.getNodeOrder(); |
| | | map.computeIfAbsent(order, k -> new ArrayList<>()).add(vo); |
| | | } |
| | | return new ArrayList<>(map.values()); |
| | | } |
| | | |
| | | /** |
| | | * 设置æµç¨é¦èç¹å¾
审人ï¼å¤å¼éå·åéï¼å
¼å®¹æ§çåå¼åæ®µï¼ |
| | | */ |
| | | private void setFirstNodeApprovers(ApproveProcess approveProcess, List<ApproveProcessConfigNodeVo> firstGroup, List<SysUser> sysUsers) { |
| | | List<Long> ids = firstGroup.stream() |
| | | .map(ApproveProcessConfigNodeVo::getApproverId) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | Map<Long, String> nameMap = sysUsers.stream() |
| | | .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (a, b) -> a)); |
| | | List<String> names = ids.stream().map(nameMap::get).filter(Objects::nonNull).collect(Collectors.toList()); |
| | | approveProcess.setApproveUserCurrentIds(ids.stream().map(String::valueOf).collect(Collectors.joining(","))); |
| | | approveProcess.setApproveUserCurrentNames(String.join(",", names)); |
| | | if (!ids.isEmpty()) { |
| | | approveProcess.setApproveUserCurrentId(ids.get(0)); |
| | | approveProcess.setApproveUserCurrentName(names.isEmpty() ? null : names.get(0)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * èç¹ç»æå¿«ç
§JSONï¼[{nodeOrder,mode,userIds,userNames}]ï¼ä¾ç¼è¾é建审æ¹èç¹ |
| | | */ |
| | | private String buildNodeConfig(List<ApproveProcessConfigNodeVo> list) { |
| | | try { |
| | | List<Map<String, Object>> nodes = new ArrayList<>(); |
| | | for (List<ApproveProcessConfigNodeVo> group : groupByOrder(list)) { |
| | | String mode = group.get(0).getApproveMode(); |
| | | if (mode == null || mode.isEmpty()) { |
| | | mode = "or"; |
| | | } |
| | | List<Long> ids = group.stream().map(ApproveProcessConfigNodeVo::getApproverId).distinct().collect(Collectors.toList()); |
| | | List<SysUser> users = sysUserMapper.selectUserByIds(ids); |
| | | Map<String, Object> node = new LinkedHashMap<>(); |
| | | node.put("nodeOrder", group.get(0).getNodeOrder()); |
| | | node.put("mode", mode); |
| | | node.put("userIds", ids.stream().map(String::valueOf).collect(Collectors.joining(","))); |
| | | node.put("userNames", users.stream().map(SysUser::getNickName).collect(Collectors.joining(","))); |
| | | nodes.add(node); |
| | | } |
| | | return OBJECT_MAPPER.writeValueAsString(nodes); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private List<String> splitIds(String ids) { |
| | | if (ids == null || ids.trim().isEmpty()) { |
| | | return new ArrayList<>(); |
| | | } |
| | | return Arrays.stream(ids.split(",")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList()); |
| | | } |
| | | |
| | | private List<Long> parseUserIds(String ids) { |
| | | return splitIds(ids).stream().map(Long::parseLong).collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * é建审æ¹èç¹ï¼ä¼å
æ approve_node_config å¿«ç
§ä¿åç»ä¸æ¨¡å¼éå»ºï¼ |
| | | * æ°éçæå¹³å®¡æ¹äººä¸²æèç¹æ§½ä½é¡ºåºä¾æ¬¡å¡«å
ï¼æ å¿«ç
§ååéæå¹³é»è¾ï¼ä¸èç¹ä¸äºº orï¼ |
| | | */ |
| | | private void rebuildApproveNodes(ApproveProcess approveProcess, String approveUserIds) { |
| | | List<ApproveProcessConfigNodeVo> config = null; |
| | | if (StringUtils.hasText(approveProcess.getApproveNodeConfig())) { |
| | | config = buildConfigFromSnapshot(approveProcess.getApproveNodeConfig(), approveUserIds); |
| | | } |
| | | if (config == null) { |
| | | approveNodeService.initApproveNodes(approveUserIds, approveProcess.getApproveId(), approveProcess.getTenantId()); |
| | | } else { |
| | | approveNodeService.initApproveNodes(config, approveProcess.getApproveId(), approveProcess.getTenantId()); |
| | | } |
| | | } |
| | | |
| | | private List<ApproveProcessConfigNodeVo> buildConfigFromSnapshot(String snapshotJson, String approveUserIds) { |
| | | List<String> newIds = splitIds(approveUserIds); |
| | | try { |
| | | List<Map<String, Object>> nodes = OBJECT_MAPPER.readValue(snapshotJson, |
| | | new TypeReference<List<Map<String, Object>>>() {}); |
| | | List<ApproveProcessConfigNodeVo> config = new ArrayList<>(); |
| | | int cursor = 0; |
| | | for (Map<String, Object> node : nodes) { |
| | | Object orderObj = node.get("nodeOrder"); |
| | | int nodeOrder = orderObj instanceof Number ? ((Number) orderObj).intValue() : 0; |
| | | String mode = node.get("mode") == null ? "or" : String.valueOf(node.get("mode")); |
| | | List<String> snapshotIds = splitIds(node.get("userIds") == null ? null : String.valueOf(node.get("userIds"))); |
| | | int slot = Math.max(1, snapshotIds.size()); |
| | | for (int j = 0; j < slot; j++) { |
| | | String uid = cursor < newIds.size() ? newIds.get(cursor++) : (j < snapshotIds.size() ? snapshotIds.get(j) : null); |
| | | if (uid == null) { |
| | | continue; |
| | | } |
| | | ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo(); |
| | | vo.setNodeOrder(nodeOrder); |
| | | vo.setApproverId(Long.parseLong(uid)); |
| | | vo.setApproveMode(mode); |
| | | config.add(vo); |
| | | } |
| | | } |
| | | // æ°é审æ¹äººè¥å¤äºå¿«ç
§æ§½ä½ï¼è¿½å å°æåä¸ä¸ªèç¹ |
| | | while (cursor < newIds.size()) { |
| | | ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo(); |
| | | vo.setNodeOrder(nodes.isEmpty() ? 1 : ((Number) nodes.get(nodes.size() - 1).get("nodeOrder")).intValue()); |
| | | vo.setApproverId(Long.parseLong(newIds.get(cursor++))); |
| | | vo.setApproveMode("or"); |
| | | config.add(vo); |
| | | } |
| | | return config; |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å·æ°æµç¨å½å审æ¹äººä¸ºç¬¬ä¸èç¹å¾
审人ï¼ç¨äºç¼è¾åéå»ºï¼ |
| | | */ |
| | | private void refreshCurrentApprovers(ApproveProcess approveProcess) { |
| | | List<ApproveNode> first = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId()) |
| | | .eq(ApproveNode::getApproveNodeOrder, 1) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | .orderByAsc(ApproveNode::getId)); |
| | | if (first.isEmpty()) { |
| | | approveProcess.setApproveUserCurrentIds(null); |
| | | approveProcess.setApproveUserCurrentNames(null); |
| | | approveProcess.setApproveUserCurrentId(null); |
| | | approveProcess.setApproveUserCurrentName(null); |
| | | } else { |
| | | approveProcess.setApproveUserCurrentIds(first.stream() |
| | | .map(n -> String.valueOf(n.getApproveNodeUserId())).collect(Collectors.joining(","))); |
| | | approveProcess.setApproveUserCurrentNames(first.stream() |
| | | .map(ApproveNode::getApproveNodeUser).collect(Collectors.joining(","))); |
| | | approveProcess.setApproveUserCurrentId(first.get(0).getApproveNodeUserId()); |
| | | approveProcess.setApproveUserCurrentName(first.get(0).getApproveNodeUser()); |
| | | } |
| | | approveProcessMapper.updateById(approveProcess); |
| | | } |
| | | |
| | | private List<Long> firstGroupUserIds(ApproveProcess approveProcess) { |
| | | List<ApproveNode> first = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>() |
| | | .eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId()) |
| | | .eq(ApproveNode::getApproveNodeOrder, 1) |
| | | .eq(ApproveNode::getDeleteFlag, 0) |
| | | .orderByAsc(ApproveNode::getId)); |
| | | return first.stream().map(ApproveNode::getApproveNodeUserId).distinct().collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * éç¥ç¬¬ä¸èç¹å
¨é¨å¾
审人 |
| | | */ |
| | | private void notifyApproveUsers(ApproveProcess approveProcess, List<Long> userIds) { |
| | | if (userIds == null || userIds.isEmpty()) { |
| | | return; |
| | | } |
| | | List<Long> ids = userIds.stream().distinct().collect(Collectors.toList()); |
| | | if (approveProcess.getApproveType() == 8) { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | ids, |
| | | "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } else { |
| | | sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()), |
| | | approveProcess.getApproveId() + "æµç¨ç¼å·ç审æ¹éè¦æ¨å®¡æ ¸!!!!!", |
| | | ids, |
| | | "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId()); |
| | | } |
| | | } |
| | | |
| | | //审æ¹ç±»åè·å(ä¸å端页é¢å¯¹åº) |
| | | private String approveProcessType(Integer approveType) { |
| | |
| | | return "å货审æ¹"; |
| | | case 8: |
| | | return "å±é©ä½ä¸å®¡æ¹"; |
| | | case 9: |
| | | return "ç¨å°å®¡æ¹"; |
| | | } |
| | | return null; |
| | | } |
| | |
| | | package com.ruoyi.collaborativeApproval.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.approve.pojo.KnowledgeBase; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessVO; |
| | | import com.ruoyi.approve.service.IApproveProcessService; |
| | | import com.ruoyi.collaborativeApproval.dto.SealApplicationManagementDTO; |
| | | import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement; |
| | | import com.ruoyi.collaborativeApproval.service.SealApplicationManagementService; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.project.system.service.ISysNoticeService; |
| | | import com.ruoyi.sales.mapper.CommonFileMapper; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.Arrays; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @AllArgsConstructor |
| | | @RestController |
| | |
| | | private SealApplicationManagementService sealApplicationManagementService; |
| | | |
| | | @Autowired |
| | | private ISysNoticeService sysNoticeService; |
| | | private IApproveProcessService approveProcessService; |
| | | |
| | | @Autowired |
| | | private CommonFileMapper commonFileMapper; |
| | | |
| | | @GetMapping("/getList") |
| | | @ApiOperation("å页æ¥è¯¢") |
| | | public AjaxResult listPage(Page page, SealApplicationManagement sealApplicationManagement){ |
| | | return AjaxResult.success(sealApplicationManagementService.listPage(page,sealApplicationManagement)); |
| | | IPage<SealApplicationManagementDTO> result = sealApplicationManagementService.listPage(page,sealApplicationManagement); |
| | | for (SealApplicationManagementDTO record : result.getRecords()) { |
| | | if (record.getApproveProcessId() != null) { |
| | | record.setCommonFileList(commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>() |
| | | .eq(CommonFile::getCommonId, record.getApproveProcessId()) |
| | | .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue()))); |
| | | } |
| | | } |
| | | return AjaxResult.success(result); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | @ApiOperation("æ°å¢") |
| | | public AjaxResult add(@RequestBody SealApplicationManagement sealApplicationManagement){ |
| | | sealApplicationManagementService.save(sealApplicationManagement); |
| | | //æ¶æ¯éç¥ |
| | | sysNoticeService.simpleNoticeByUser("ç¨å°å®¡æ¹", |
| | | "ç³è¯·ç¼å·ï¼"+sealApplicationManagement.getApplicationNum()+"\t" |
| | | +"ç³è¯·æ é¢ï¼"+sealApplicationManagement.getTitle(), |
| | | Arrays.asList(sealApplicationManagement.getApproveUserId()), |
| | | "/collaborativeApproval/sealManagement?applicationNum="+sealApplicationManagement.getApplicationNum()); |
| | | @ApiOperation("æ°å¢/éæ°ç³è¯·ç¨å°") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult add(@RequestBody SealApplicationManagement sealApplicationManagement) throws Exception { |
| | | sealApplicationManagement.setStatus("pending"); |
| | | if (sealApplicationManagement.getId() == null) { |
| | | sealApplicationManagementService.save(sealApplicationManagement); |
| | | } else { |
| | | // éæ°ç³è¯·ï¼æ¸
çæ§å®¡æ¹æµç¨å
³èçéä»¶ï¼é¿å
éç |
| | | SealApplicationManagement old = sealApplicationManagementService.getById(sealApplicationManagement.getId()); |
| | | if (old != null && old.getApproveProcessId() != null) { |
| | | commonFileMapper.delete(new LambdaQueryWrapper<CommonFile>() |
| | | .eq(CommonFile::getCommonId, old.getApproveProcessId()) |
| | | .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue())); |
| | | } |
| | | sealApplicationManagementService.updateById(sealApplicationManagement); |
| | | } |
| | | // åèµ·ååç»ä¸å®¡æ ¸æµç¨ï¼ç¨å°å®¡æ¹ï¼ |
| | | ApproveProcessVO vo = new ApproveProcessVO(); |
| | | vo.setApproveType(9); |
| | | vo.setApproveReason(sealApplicationManagement.getApplicationNum() + "ï¼" + sealApplicationManagement.getTitle()); |
| | | vo.setApproveDeptId(sealApplicationManagement.getDeptId()); |
| | | vo.setApproveTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())); |
| | | Long approveProcessId = approveProcessService.addApprove(vo); |
| | | // åå¡«å®¡æ¹æµç¨idï¼ä¾å®¡æ¹åè°æ´æ°ç¶æã详æ
æ¥è¯¢éä»¶ |
| | | sealApplicationManagement.setApproveProcessId(approveProcessId); |
| | | sealApplicationManagementService.updateById(sealApplicationManagement); |
| | | // ä¿åç¨å°ç³è¯·éä»¶ï¼å
³èå°å®¡æ¹æµç¨ |
| | | if (!CollectionUtils.isEmpty(sealApplicationManagement.getAttachmentList())) { |
| | | for (CommonFile cf : sealApplicationManagement.getAttachmentList()) { |
| | | CommonFile record = new CommonFile(); |
| | | record.setCommonId(approveProcessId); |
| | | record.setName(cf.getName()); |
| | | record.setUrl(cf.getUrl()); |
| | | record.setType(FileNameType.ApproveProcess.getValue()); |
| | | record.setCreateTime(LocalDateTime.now()); |
| | | record.setUpdateTime(LocalDateTime.now()); |
| | | commonFileMapper.insert(record); |
| | | } |
| | | } |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | |
| | | return AjaxResult.success(sealApplicationManagementService.removeBatchByIds(ids)); |
| | | } |
| | | |
| | | @GetMapping("/detail") |
| | | @ApiOperation("ç¨å°ç³è¯·è¯¦æ
ï¼æå®¡æ¹æµç¨idï¼") |
| | | public AjaxResult detail(Long approveProcessId){ |
| | | SealApplicationManagement seal = sealApplicationManagementService.getOne(new LambdaQueryWrapper<SealApplicationManagement>() |
| | | .eq(SealApplicationManagement::getApproveProcessId, approveProcessId) |
| | | .last("limit 1")); |
| | | if (seal == null) { |
| | | throw new RuntimeException("ç¨å°ç³è¯·ä¸åå¨"); |
| | | } |
| | | seal.setCommonFileList(commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>() |
| | | .eq(CommonFile::getCommonId, approveProcessId) |
| | | .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue()))); |
| | | return AjaxResult.success(seal); |
| | | } |
| | | |
| | | @ApiOperation(value = "ç¨å°ç³è¯·ç®¡ç导åº") |
| | | @PostMapping("/export") |
| | | public void export(HttpServletResponse response) { |
| | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @TableName("seal_application_management") |
| | |
| | | * 审æ¹äºº |
| | | */ |
| | | private Long approveUserId; |
| | | |
| | | /** |
| | | * å
³èçååå®¡æ¹æµç¨ä¸»é®idï¼approve_process.idï¼ |
| | | */ |
| | | @ApiModelProperty("ååå®¡æ¹æµç¨id") |
| | | private Long approveProcessId; |
| | | |
| | | /** |
| | | * éä»¶åè¡¨ï¼æäº¤ç¨ï¼æ¥èªå端 /common/upload ä¸ä¼ ç»æï¼ |
| | | */ |
| | | @TableField(exist = false) |
| | | private List<CommonFile> attachmentList; |
| | | |
| | | /** |
| | | * éä»¶åè¡¨ï¼æ¥è¯¢å±ç¤ºç¨ï¼ |
| | | */ |
| | | @TableField(exist = false) |
| | | private List<CommonFile> commonFileList; |
| | | /** |
| | | * å建è
|
| | | */ |
| | |
| | | } |
| | | } |
| | | |
| | | wrapper.orderByDesc(CustomerVisits::getPurposeDate); |
| | | |
| | | return customerVisitsMapper.selectPage(page, wrapper); |
| | | } |
| | | |
| | |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | |
| | | private Boolean hasUnreportedMachine; |
| | | |
| | | private String finalProductModel; |
| | | |
| | | //å æ¾æ° |
| | | @ApiModelProperty(value = "å æ¾æ°") |
| | | private String processRouteAddNum; |
| | | |
| | | @ApiModelProperty("æ¥å·¥çç»é»è®¤æå(id+å§å)") |
| | | private List<ReportPerson> reportPersons; |
| | | |
| | | @Data |
| | | public static class ReportPerson { |
| | | private Long userId; |
| | | private String userName; |
| | | } |
| | | } |
| | |
| | | private Long deviceId; |
| | | private String deviceName; |
| | | private String workMinutes; |
| | | private String personWorkMinutes; |
| | | |
| | | private List<Team> teamList; |
| | | |
| | | @ApiModelProperty("æ¥å·¥çç»äººåäº§éæ¶é¿æç»") |
| | | private List<Person> personList; |
| | | |
| | | |
| | | |
| | |
| | | private Long userId; |
| | | private String userName; |
| | | } |
| | | |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public static class Person { |
| | | private Long userId; |
| | | private String userName; |
| | | private BigDecimal quantity; // 该人å产é |
| | | private Integer workHour; // 该人åç产æ¶é¿(åé) |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.production.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.production.pojo.ProductionReportPerson; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | @Mapper |
| | | public interface ProductionReportPersonMapper extends BaseMapper<ProductionReportPerson> { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.production.pojo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * æ¥å·¥çç»äººåäº§éæ¶é¿æç» |
| | | */ |
| | | @Data |
| | | @TableName("production_report_person") |
| | | @ApiModel(value = "ProductionReportPerson对象", description = "æ¥å·¥çç»äººåäº§éæ¶é¿æç»è¡¨") |
| | | public class ProductionReportPerson { |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("æ¥å·¥ä¸»è¡¨id(production_product_main.id)") |
| | | private Long productMainId; |
| | | |
| | | @ApiModelProperty("ç产人id") |
| | | private Long userId; |
| | | |
| | | @ApiModelProperty("ç产人å§å") |
| | | private String userName; |
| | | |
| | | @ApiModelProperty("该人åäº§åºæ°é") |
| | | private BigDecimal quantity; |
| | | |
| | | @ApiModelProperty("该人åç产æ¶é¿(åé)") |
| | | private Integer workHour; |
| | | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long tenantId; |
| | | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long createUser; |
| | | |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateUser; |
| | | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | } |
| | |
| | | void nextAddProductMain(@NotNull ProductionProductOutput productionProductOutput); |
| | | |
| | | ArrayList<Long> listMain(List<Long> idList); |
| | | |
| | | /** |
| | | * æäº§ä¸è¾¾åï¼ä¸ºç¬¬ä¸ééè´¨æ£å·¥åºé¢çæè¿ç¨/åºåæ£éªè´¨æ£å |
| | | */ |
| | | void preGenerateQualityInspectForOrder(Long productOrderId); |
| | | |
| | | /** |
| | | * æ¸
çæäº§é¢çæçè´¨æ£åï¼æªå
³èæ¥å·¥ï¼ |
| | | */ |
| | | void cleanPreGeneratedQualityInspects(List<Long> workOrderIds); |
| | | } |
| | |
| | | private ProductOrderService productOrderService; |
| | | @Autowired |
| | | private ProductProcessService productProcessService; |
| | | @Autowired |
| | | private ProductionProductMainService productionProductMainService; |
| | | |
| | | @Override |
| | | public IPage<ProcessRouteDto> pageProcessRouteDto(Page<ProcessRouteDto> page, ProcessRouteDto processRouteDto) { |
| | |
| | | |
| | | // 6. æ°å¢ç产工èºè·¯çº¿å表 |
| | | buildProductProcessRouteItems(processRouteAnticlockwiseDtos, productProcessRoute.getId(), productModelId, productOrderId); |
| | | // æäº§ä¸è¾¾åèªå¨è§¦å第ä¸ééè´¨æ£å·¥åºçè¿ç¨æ£éª |
| | | productionProductMainService.preGenerateQualityInspectForOrder(productOrderId); |
| | | return processRoute.getId(); |
| | | } |
| | | |
| | |
| | | import com.ruoyi.production.service.ProductProcessService; |
| | | import com.ruoyi.production.service.ProductWorkOrderService; |
| | | import com.ruoyi.production.service.ProductionPrintOrderService; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | @Autowired |
| | | private StockUtils stockUtils; |
| | | @Autowired |
| | | private ProductionProductMainService productionProductMainService; |
| | | |
| | | @Override |
| | | public IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder) { |
| | |
| | | productProcessRouteItem.setProductOrderId(productOrder.getId()); |
| | | productProcessRouteItem.setProductRouteId(productProcessRoute.getId()); |
| | | productProcessRouteItem.setDragSort(processRouteItem.getDragSort()); |
| | | productProcessRouteItem.setIsQuality(processRouteItem.getIsQuality()); |
| | | int insert = productProcessRouteItemMapper.insert(productProcessRouteItem); |
| | | if (insert > 0) { |
| | | |
| | |
| | | productWorkOrderMapper.insert(productWorkOrder); |
| | | } |
| | | } |
| | | // æäº§ä¸è¾¾åèªå¨è§¦å第ä¸ééè´¨æ£å·¥åºçè¿ç¨æ£éª |
| | | productionProductMainService.preGenerateQualityInspectForOrder(productOrder.getId()); |
| | | return productOrderMapper.updateById(productOrder); |
| | | } |
| | | |
| | |
| | | if (productionProductMains.size() > 0) { |
| | | throw new RuntimeException("ç产订åå·²ç»å¼å§ç产,ä¸è½å é¤"); |
| | | } |
| | | // æ¸
çæäº§é¢çæçè´¨æ£å |
| | | productionProductMainService.cleanPreGeneratedQualityInspects( |
| | | productWorkOrders.stream().map(ProductWorkOrder::getId).collect(Collectors.toList())); |
| | | //å é¤å·¥å |
| | | productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids)); |
| | | } |
| | |
| | | private ProductionProductMainMapper productionProductMainMapper; |
| | | |
| | | private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | private ProductionReportPersonMapper productionReportPersonMapper; |
| | | |
| | | private ProductWorkOrderMapper productWorkOrderMapper; |
| | | |
| | |
| | | // .eq(QualityInspect::getProductMainId, mainId)); |
| | | salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>() |
| | | .eq(SalesLedgerProductionAccounting::getProductMainId, main.getId())); |
| | | productionReportPersonMapper.delete(new LambdaQueryWrapper<ProductionReportPerson>() |
| | | .eq(ProductionReportPerson::getProductMainId, main.getId())); |
| | | } |
| | | } |
| | | // æ¥è¯¢è®¢å + å 餿 ¸ç® |
| | | |
| | | // æ¸
çæäº§é¢çæçè´¨æ£å |
| | | productionProductMainService.cleanPreGeneratedQualityInspects(Collections.singletonList(workOrderId)); |
| | | |
| | | // å é¤å
³èå·¥å |
| | | productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId)); |
| | |
| | | import com.ruoyi.production.dto.ProductWorkOrderDto; |
| | | import com.ruoyi.production.mapper.ProductWorkOrderFileMapper; |
| | | import com.ruoyi.production.mapper.ProductWorkOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionMachineRecordMapper; |
| | | import com.ruoyi.production.pojo.ProductWorkOrder; |
| | | import com.ruoyi.production.pojo.ProductWorkOrderFile; |
| | | import com.ruoyi.production.pojo.ProductionMachineRecord; |
| | | import com.ruoyi.production.service.ProductWorkOrderService; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | @Service |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | private ProductWorkOrderMapper productWorkOrderMapper; |
| | | @Autowired |
| | | private ProductWorkOrderFileMapper productWorkOrderFileMapper; |
| | | @Autowired |
| | | private ProductionMachineRecordMapper productionMachineRecordMapper; |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | @Value("${file.temp-dir}") |
| | | private String tempDir; |
| | |
| | | |
| | | @Override |
| | | public ProductWorkOrderDto getProductWorkOrderById(Long id) { |
| | | return productWorkOrderMapper.getProductWorkOrderFlowCard(id); |
| | | ProductWorkOrderDto productWorkOrderDto = productWorkOrderMapper.getProductWorkOrderFlowCard(id); |
| | | // åå¹¶å·¥åæäº§äººå䏿ºå°ä¸æºæä½åï¼å»éåä½ä¸ºæ¥å·¥å¼¹çªé»è®¤çç»æå |
| | | Set<Long> userIdSet = new LinkedHashSet<>(); |
| | | if (productWorkOrderDto != null && StrUtil.isNotBlank(productWorkOrderDto.getUserIds())) { |
| | | for (String uid : productWorkOrderDto.getUserIds().split(",")) { |
| | | if (StrUtil.isNotBlank(uid)) { |
| | | userIdSet.add(Long.parseLong(uid.trim())); |
| | | } |
| | | } |
| | | } |
| | | List<ProductionMachineRecord> machineRecords = productionMachineRecordMapper.selectList( |
| | | Wrappers.<ProductionMachineRecord>lambdaQuery() |
| | | .eq(ProductionMachineRecord::getWorkOrderId, id) |
| | | .isNotNull(ProductionMachineRecord::getOperatorId)); |
| | | for (ProductionMachineRecord machineRecord : machineRecords) { |
| | | if (StrUtil.isNotBlank(machineRecord.getOperatorId())) { |
| | | for (String uid : machineRecord.getOperatorId().split(",")) { |
| | | if (StrUtil.isNotBlank(uid)) { |
| | | userIdSet.add(Long.parseLong(uid.trim())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | List<ProductWorkOrderDto.ReportPerson> reportPersons = new ArrayList<>(); |
| | | for (Long userId : userIdSet) { |
| | | ProductWorkOrderDto.ReportPerson reportPerson = new ProductWorkOrderDto.ReportPerson(); |
| | | reportPerson.setUserId(userId); |
| | | SysUser sysUser = sysUserMapper.selectUserById(userId); |
| | | if (sysUser != null) { |
| | | reportPerson.setUserName(sysUser.getNickName()); |
| | | } |
| | | reportPersons.add(reportPerson); |
| | | } |
| | | if (productWorkOrderDto != null) { |
| | | productWorkOrderDto.setReportPersons(reportPersons); |
| | | } |
| | | return productWorkOrderDto; |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | |
| | | private ProductionReportPersonMapper productionReportPersonMapper; |
| | | |
| | | private StockUtils stockUtils; |
| | | |
| | | |
| | |
| | | productionProductMain.setAuditUserId(SecurityUtils.getUserId()); |
| | | |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | /*ä¿åæ¥å·¥çç»äººåäº§éæ¶é¿æç»*/ |
| | | List<ProductionProductMainDto.Person> personList = dto.getPersonList(); |
| | | BigDecimal personSum = BigDecimal.ZERO; |
| | | if (CollUtil.isNotEmpty(personList)) { |
| | | for (ProductionProductMainDto.Person person : personList) { |
| | | BigDecimal personQty = person.getQuantity() == null ? BigDecimal.ZERO : person.getQuantity(); |
| | | personSum = personSum.add(personQty); |
| | | ProductionReportPerson reportPerson = new ProductionReportPerson(); |
| | | reportPerson.setProductMainId(productionProductMain.getId()); |
| | | reportPerson.setUserId(person.getUserId()); |
| | | reportPerson.setUserName(person.getUserName()); |
| | | reportPerson.setQuantity(personQty); |
| | | reportPerson.setWorkHour(person.getWorkHour() != null ? person.getWorkHour() : 0); |
| | | productionReportPersonMapper.insert(reportPerson); |
| | | } |
| | | } |
| | | BigDecimal totalQuantity = dto.getQuantity() == null ? BigDecimal.ZERO : dto.getQuantity(); |
| | | if (CollUtil.isNotEmpty(personList) && personSum.compareTo(totalQuantity) != 0) { |
| | | throw new ServiceException("åçç»äº§éä¹åå¿
é¡»çäºæ¥å·¥æ»äº§é"); |
| | | } |
| | | /*æ°å¢æ¥å·¥æå
¥è¡¨*/ |
| | | List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(Optional.ofNullable(productProcessRoute.getBomId()).orElse(0), productProcess.getId()); |
| | | if (productStructureDtos.isEmpty()) { |
| | |
| | | productionProductOutput.setReplenishQty(dto.getReplenishQty()); |
| | | productionProductOutput.setAddQty(dto.getAddQty() != null ? dto.getAddQty() : BigDecimal.ZERO); |
| | | productionProductOutputMapper.insert(productionProductOutput); |
| | | //åæ ¼æ°é=æ¥å·¥æ°é-æ¥åºæ°é |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | //åªæåæ ¼æ°é>0æè½å¢å ç¸åºæ°æ® |
| | | //å·¥åºæµè½¬æ°é=äº§åºæ°é+å æ¾æ°ï¼æ¥åºä»
åæ°æ®è®°å½ï¼ä¸æ£åå·¥åºæµè½¬åºæ°ï¼åå·¥åºæ»äº§éä¿æè¿è´¯ï¼ |
| | | BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().add(addQty); |
| | | //åªæå·¥åºæµè½¬æ°é>0æè½å¢å ç¸åºæ°æ® |
| | | if (productQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); |
| | | /*æ´æ°å·¥ååç产订å*/ |
| | |
| | | if (!machineRecords.isEmpty()) { |
| | | productWorkOrder.setActualStartTime(machineRecords.get(0).getMachineStartTime()); |
| | | } |
| | | // å®é
ç»ææ¶é´ = æ¥å·¥ç»ææ¶é´ |
| | | productWorkOrder.setActualEndTime(now);//å®é
ç»ææ¶é´ä¸ºæ¥å·¥ç»ææ¶é´ |
| | | productWorkOrder.setEndProductTime(now); |
| | | productWorkOrderMapper.updateById(productWorkOrder); |
| | | // ä»
宿æ°éè¾¾å°è®¡åæ°éæ¶æå¡«å
å®é
ç»ææ¶é´ï¼æªå®æåæ¸
空已填çç»ææ¶é´ï¼å
许继ç»åæ¹æ¥å·¥ï¼ |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) >= 0) { |
| | | productWorkOrder.setActualEndTime(now); |
| | | productWorkOrder.setEndProductTime(now); |
| | | productWorkOrderMapper.updateById(productWorkOrder); |
| | | } else { |
| | | // updateById é»è®¤å¿½ç¥ null åæ®µï¼éç¨ UpdateWrapper æ¾å¼æ¸
空ï¼èªæåå²èæ°æ®ï¼ |
| | | productWorkOrderMapper.update(null, Wrappers.<ProductWorkOrder>lambdaUpdate() |
| | | .eq(ProductWorkOrder::getId, productWorkOrder.getId()) |
| | | .set(ProductWorkOrder::getActualEndTime, null) |
| | | .set(ProductWorkOrder::getEndProductTime, null)); |
| | | } |
| | | //ç产订å |
| | | ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); |
| | | if (ObjectUtils.isNull(productOrder.getStartTime())) { |
| | |
| | | // åå° æ´æ°å·¥ååç产订å |
| | | ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId()); |
| | | ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId()); |
| | | //å·¥åºæµè½¬æ°é=äº§åºæ°é+å æ¾æ°ï¼ä¸æ¥å·¥ç´¯å å£å¾ä¸è´ï¼æ¥åºä¸æ£åæµè½¬åºæ°ï¼ |
| | | BigDecimal processQty = productionProductOutput.getQuantity().add( |
| | | productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty()); |
| | | |
| | | productWorkOrder.setCompleteQuantity( |
| | | productWorkOrder.getCompleteQuantity() |
| | | .subtract(productionProductOutput.getQuantity()) |
| | | .subtract(processQty) |
| | | .max(BigDecimal.ZERO) |
| | | ); |
| | | List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId())); |
| | |
| | | //å¦ææ¯æåä¸éå·¥åºæ¥å·¥ä¹åç产订å éè¦æ£é¤ |
| | | productOrder.setCompleteQuantity( |
| | | productOrder.getCompleteQuantity() |
| | | .subtract(productionProductOutput.getQuantity()) |
| | | .subtract(processQty) |
| | | .max(BigDecimal.ZERO) |
| | | ); |
| | | if (productOrder.getCompleteQuantity().compareTo(productionProductOutput.getQuantity()) > 0) { |
| | | if (productOrder.getCompleteQuantity().compareTo(processQty) > 0) { |
| | | productOrder.setEndTime(null); |
| | | } |
| | | productOrderMapper.updateById(productOrder); |
| | | } |
| | | |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(productionProductOutput.getQuantity()) > 0) { |
| | | if (productWorkOrder.getCompleteQuantity().compareTo(processQty) > 0) { |
| | | productWorkOrder.setActualEndTime(null); |
| | | } |
| | | |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void nextAddProductMain(@NotNull ProductionProductOutput productionProductOutput) { |
| | | //åæ ¼æ°é=æ¥å·¥æ°é-æ¥åºæ°é |
| | | //å®é
å
¥åºæ°é=äº§åºæ°é+å æ¾æ°-æ¥åºæ°é |
| | | ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productionProductOutput.getProductMainId()); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().add(addQty).subtract(productionProductOutput.getScrapQty()); |
| | | ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId()); |
| | | ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId()); |
| | | //å·¥èºè·¯çº¿ä¸å½åå·¥åºå¯¹åºç产åºè§æ ¼åå· |
| | |
| | | inspectType = 2; |
| | | process = null; |
| | | } |
| | | Product product = productMapper.selectById(productModel.getProductId()); |
| | | QualityInspect qualityInspect = new QualityInspect(); |
| | | qualityInspect.setProductId(product.getId()); |
| | | qualityInspect.setProductName(product.getProductName()); |
| | | qualityInspect.setModel(productModel.getModel()); |
| | | qualityInspect.setUnit(productModel.getUnit()); |
| | | qualityInspect.setQuantity(productQty); |
| | | qualityInspect.setProcess(process); |
| | | qualityInspect.setInspectState(0); |
| | | qualityInspect.setInspectType(inspectType); |
| | | qualityInspect.setProductMainId(productionProductMain.getId()); |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | | if (!qualityTestStandard.isEmpty()) { |
| | | qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery() |
| | | .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//é»è®¤è·åææ°ç |
| | | .forEach(qualityTestStandardParam -> { |
| | | QualityInspectParam param = new QualityInspectParam(); |
| | | BeanUtils.copyProperties(qualityTestStandardParam, param); |
| | | param.setId(null); |
| | | param.setInspectId(qualityInspect.getId()); |
| | | qualityInspectParamMapper.insert(param); |
| | | }); |
| | | // æäº§ä¸è¾¾æ¶å·²ä¸ºè¯¥å·¥åé¢çæè´¨æ£åï¼product_main_id IS NULLï¼ï¼æ¥å·¥å®¡æ ¸æ¶è®¤é¢å¹¶æ´æ°ä¸ºå®é
æ°é |
| | | QualityInspect preInspect = qualityInspectMapper.selectOne( |
| | | Wrappers.<QualityInspect>lambdaQuery() |
| | | .eq(QualityInspect::getWorkOrderId, productionProductMain.getWorkOrderId()) |
| | | .isNull(QualityInspect::getProductMainId) |
| | | .last("limit 1")); |
| | | if (preInspect != null) { |
| | | preInspect.setProductMainId(productionProductMain.getId()); |
| | | preInspect.setQuantity(productQty); |
| | | if (preInspect.getInspectState() != null && preInspect.getInspectState() == 1 |
| | | && preInspect.getInspectType() != null && preInspect.getInspectType() == 2) { |
| | | // å·²æäº¤ä¸ä¸ºåºåæ£ï¼å é¤æè®¡åæ°éå
¥åºçè®°å½ï¼æå®é
æ°ééæ°å
¥åº |
| | | stockUtils.deleteStockInRecord(preInspect.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()); |
| | | stockUtils.addStock(productModel.getId(), productQty, StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), preInspect.getId(), "-", "-", "-"); |
| | | } |
| | | qualityInspectMapper.updateById(preInspect); |
| | | } else { |
| | | insertQualityInspect(productProcessRouteItem, inspectType, process, productionProductMain.getId(), productionProductMain.getWorkOrderId(), productQty); |
| | | } |
| | | } else { |
| | | //ç´æ¥å
¥åº |
| | |
| | | /*æ·»å çäº§æ ¸ç® åºåå·¥åºæ¯è®¡ä»¶è¿æ¯è®¡æ¶*/ |
| | | BigDecimal workHours = productProcess.getSalaryQuota(); |
| | | List<ProductionMachineRecord> productionMachineRecords = productionMachineRecordMapper.selectList(Wrappers.<ProductionMachineRecord>lambdaQuery().eq(ProductionMachineRecord::getWorkOrderId, productionProductMain.getWorkOrderId())); |
| | | if (ObjectUtils.isNotEmpty(productionMachineRecords)) { |
| | | // æ¥å·¥çç»äººåäº§éæ¶é¿æç»ï¼ææç»åæäººçææ ¸ç®ï¼æ æç»ååéæºå°æä½åé»è¾ï¼ |
| | | List<ProductionReportPerson> personList = productionReportPersonMapper.selectList(Wrappers.<ProductionReportPerson>lambdaQuery().eq(ProductionReportPerson::getProductMainId, productionProductMain.getId())); |
| | | // 设å¤åæ¥å·¥å设å¤ï¼æªå¡«åæ¶åéå该工åä»»ä¸å°æº |
| | | Long reportDeviceId = productionProductMain.getDeviceId() != null |
| | | ? productionProductMain.getDeviceId() |
| | | : productionMachineRecords.stream().map(ProductionMachineRecord::getMachineId).filter(Objects::nonNull).findFirst().orElse(null); |
| | | if (CollUtil.isNotEmpty(personList)) { |
| | | // æ¯æ¬¡æ¥å·¥ç¬ç«æäººçææ ¸ç®ï¼æ¯æåæ¹æ¥å·¥ç´è³å®æï¼ï¼ä¸å䏿ºè®°å½æ¥å·¥ç¶æå½±å |
| | | BigDecimal netQty = productQty; |
| | | BigDecimal rawQuantity = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity(); |
| | | for (ProductionReportPerson person : personList) { |
| | | BigDecimal personQty = person.getQuantity() == null ? BigDecimal.ZERO : person.getQuantity(); |
| | | BigDecimal finishedNum; |
| | | if (netQty.compareTo(rawQuantity) == 0 || rawQuantity.compareTo(BigDecimal.ZERO) == 0) { |
| | | // æ æ¥åºï¼ææ¯äº§é为0ï¼æ¶åå¼å³æ¯äº§éï¼ç´æ¥å个人产é |
| | | finishedNum = personQty; |
| | | } else { |
| | | // ææ¥åºæ¶æå人æ¯äº§éå æ¯åæåå¼ï¼åèäºå
¥ä¿ç2ä½ |
| | | finishedNum = personQty.multiply(netQty).divide(rawQuantity, 2, BigDecimal.ROUND_HALF_UP); |
| | | } |
| | | SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder() |
| | | .productMainId(productionProductMain.getId()) |
| | | .schedulingUserId(person.getUserId()) |
| | | .schedulingUserName(person.getUserName()) |
| | | .finishedNum(finishedNum) |
| | | .workHours(workHours) |
| | | .process(productProcess.getName()) |
| | | .schedulingDate(LocalDate.now()) |
| | | .tenantId(productionProductOutput.getTenantId()) |
| | | .deviceId(reportDeviceId) |
| | | .workHour(person.getWorkHour() == null ? 0L : person.getWorkHour().longValue()) |
| | | .build(); |
| | | salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting); |
| | | } |
| | | // 该工å䏿ºè®°å½æ¬æ¬¡å·²æ¥å·¥ |
| | | for (ProductionMachineRecord productionMachineRecord : productionMachineRecords) { |
| | | if (!productionMachineRecord.getReportStatus()) { |
| | | productionMachineRecord.setReportStatus(true); |
| | | productionMachineRecordMapper.updateById(productionMachineRecord); |
| | | } |
| | | } |
| | | } else if (ObjectUtils.isNotEmpty(productionMachineRecords)) { |
| | | // å
¼å®¹æ§æ°æ®ï¼æªä¼ 人åæç»ååéææªæ¥å·¥çæºå°ä¸æºæä½åçææ ¸ç® |
| | | for (ProductionMachineRecord productionMachineRecord : productionMachineRecords) { |
| | | //说æå·²ç»æ·»å è¿äºï¼ä¸æ·»å äº |
| | | if (productionMachineRecord.getReportStatus()) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * çæè´¨æ£åå¹¶åå¡«æ£æµæ å/æ£éªåæ° |
| | | */ |
| | | private void insertQualityInspect(ProductProcessRouteItem routeItem, Integer inspectType, String process, |
| | | Long productMainId, Long workOrderId, BigDecimal quantity) { |
| | | ProductModel productModel = productModelMapper.selectById(routeItem.getProductModelId()); |
| | | Product product = productMapper.selectById(productModel.getProductId()); |
| | | QualityInspect qualityInspect = new QualityInspect(); |
| | | qualityInspect.setProductId(product.getId()); |
| | | qualityInspect.setProductName(product.getProductName()); |
| | | qualityInspect.setModel(productModel.getModel()); |
| | | qualityInspect.setUnit(productModel.getUnit()); |
| | | qualityInspect.setQuantity(quantity); |
| | | qualityInspect.setProcess(process); |
| | | qualityInspect.setInspectState(0); |
| | | qualityInspect.setInspectType(inspectType); |
| | | qualityInspect.setProductMainId(productMainId); |
| | | qualityInspect.setWorkOrderId(workOrderId); |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | | if (!qualityTestStandard.isEmpty()) { |
| | | qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery() |
| | | .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//é»è®¤è·åææ°ç |
| | | .forEach(qualityTestStandardParam -> { |
| | | QualityInspectParam param = new QualityInspectParam(); |
| | | BeanUtils.copyProperties(qualityTestStandardParam, param); |
| | | param.setId(null); |
| | | param.setInspectId(qualityInspect.getId()); |
| | | qualityInspectParamMapper.insert(param); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void preGenerateQualityInspectForOrder(Long productOrderId) { |
| | | if (productOrderId == null) { |
| | | return; |
| | | } |
| | | ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectOne( |
| | | Wrappers.<ProductProcessRoute>lambdaQuery() |
| | | .eq(ProductProcessRoute::getProductOrderId, productOrderId)); |
| | | if (productProcessRoute == null) { |
| | | return; |
| | | } |
| | | List<ProductProcessRouteItem> items = productProcessRouteItemMapper.selectList( |
| | | Wrappers.<ProductProcessRouteItem>lambdaQuery() |
| | | .eq(ProductProcessRouteItem::getProductRouteId, productProcessRoute.getId()) |
| | | .orderByAsc(ProductProcessRouteItem::getDragSort) |
| | | .orderByAsc(ProductProcessRouteItem::getId)); |
| | | if (items.isEmpty()) { |
| | | return; |
| | | } |
| | | // 第ä¸éå·¥åºéè´¨æ£æé¢çæ |
| | | ProductProcessRouteItem first = items.get(0); |
| | | if (!Boolean.TRUE.equals(first.getIsQuality())) { |
| | | return; |
| | | } |
| | | ProductWorkOrder workOrder = productWorkOrderMapper.selectOne( |
| | | Wrappers.<ProductWorkOrder>lambdaQuery() |
| | | .eq(ProductWorkOrder::getProductProcessRouteItemId, first.getId())); |
| | | if (workOrder == null) { |
| | | return; |
| | | } |
| | | // 该工åå·²åå¨é¢çæè´¨æ£ååä¸éå¤çæ |
| | | Long existCount = qualityInspectMapper.selectCount( |
| | | Wrappers.<QualityInspect>lambdaQuery() |
| | | .eq(QualityInspect::getWorkOrderId, workOrder.getId()) |
| | | .isNull(QualityInspect::getProductMainId)); |
| | | if (existCount != null && existCount > 0) { |
| | | return; |
| | | } |
| | | boolean onlyOne = items.size() == 1; |
| | | int inspectType = onlyOne ? 2 : 1; |
| | | String process = null; |
| | | if (!onlyOne) { |
| | | ProductProcess processEntity = productProcessMapper.selectById(first.getProcessId()); |
| | | if (processEntity != null) { |
| | | process = processEntity.getName(); |
| | | } |
| | | } |
| | | insertQualityInspect(first, inspectType, process, null, workOrder.getId(), workOrder.getPlanQuantity()); |
| | | } |
| | | |
| | | @Override |
| | | public void cleanPreGeneratedQualityInspects(List<Long> workOrderIds) { |
| | | if (CollUtil.isEmpty(workOrderIds)) { |
| | | return; |
| | | } |
| | | List<QualityInspect> preInspects = qualityInspectMapper.selectList( |
| | | Wrappers.<QualityInspect>lambdaQuery() |
| | | .in(QualityInspect::getWorkOrderId, workOrderIds) |
| | | .isNull(QualityInspect::getProductMainId)); |
| | | if (CollUtil.isEmpty(preInspects)) { |
| | | return; |
| | | } |
| | | for (QualityInspect pre : preInspects) { |
| | | if (pre.getInspectState() != null && pre.getInspectState() == 1) { |
| | | throw new ServiceException("å·²æäº¤çæ£éªåä¸è½å é¤"); |
| | | } |
| | | } |
| | | List<Long> inspectIds = preInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()); |
| | | qualityInspectParamMapper.delete( |
| | | Wrappers.<QualityInspectParam>lambdaQuery().in(QualityInspectParam::getInspectId, inspectIds)); |
| | | qualityInspectMapper.deleteBatchIds(inspectIds); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean removeProductMain(Long id) { |
| | | //å¤æè¯¥æ¡æ¥å·¥æ¯å¦ä¸åæ ¼å¤ç,妿ä¸åæ ¼å¤çäºï¼åä¸å
许å é¤ |
| | |
| | | new LambdaQueryWrapper<SalesLedgerProductionAccounting>() |
| | | .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId()) |
| | | ); |
| | | /*å 餿¥å·¥çç»äººåäº§éæ¶é¿æç»*/ |
| | | productionReportPersonMapper.delete( |
| | | new LambdaQueryWrapper<ProductionReportPerson>() |
| | | .eq(ProductionReportPerson::getProductMainId, productionProductMain.getId()) |
| | | ); |
| | | /*æ´æ°å·¥ååç产订å*/ |
| | | ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId()); |
| | | if (productWorkOrder != null && productionProductOutput != null) { |
| | | BigDecimal outputQty = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity(); |
| | | BigDecimal scrapQty = productionProductOutput.getScrapQty() == null ? BigDecimal.ZERO : productionProductOutput.getScrapQty(); |
| | | BigDecimal addQty = productionProductOutput.getAddQty() == null ? BigDecimal.ZERO : productionProductOutput.getAddQty(); |
| | | BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity(); |
| | | |
| | | // å¿
é¡»ä¸ºå®¡æ ¸éè¿çæä¼åå°æ°é |
| | | |
| | | |
| | | BigDecimal validQuantity = outputQty.subtract(scrapQty); |
| | | BigDecimal validQuantity = outputQty.add(addQty); |
| | | if (productionProductMain.getAuditStatus() != 2) { |
| | | productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity).max(BigDecimal.ZERO)); |
| | | } |
| | |
| | | if (productOrder != null) { |
| | | BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity(); |
| | | BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO; |
| | | BigDecimal scrapQty = productionProductOutput.getScrapQty() != null ? productionProductOutput.getScrapQty() : BigDecimal.ZERO; |
| | | BigDecimal actualQualifiedQty = totalQty.subtract(scrapQty); |
| | | BigDecimal addQty = productionProductOutput.getAddQty() != null ? productionProductOutput.getAddQty() : BigDecimal.ZERO; |
| | | BigDecimal actualQualifiedQty = totalQty.add(addQty); |
| | | BigDecimal newCompleteQty = orderCompleteQty.subtract(actualQualifiedQty); |
| | | productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty); |
| | | productOrder.setEndTime(null); |
| | |
| | |
|
| | | import java.io.File;
|
| | | import java.util.ArrayList;
|
| | | import java.util.LinkedHashMap;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpServletResponse;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * éç¨ä¸ä¼ 请æ±ï¼å¤ä¸ªï¼è¿åæä»¶å表ï¼ä¾éä»¶ä¸ä¼ ç»ä»¶ä½¿ç¨ï¼
|
| | | */
|
| | | @PostMapping("/uploadsList")
|
| | | @ApiOperation(value = "éç¨ä¸ä¼ 请æ±ï¼å¤ä¸ªï¼è¿åæä»¶å表ï¼")
|
| | | public AjaxResult uploadsList(List<MultipartFile> files) throws Exception
|
| | | {
|
| | | try
|
| | | {
|
| | | if (files == null || files.isEmpty())
|
| | | {
|
| | | return AjaxResult.error("æªéæ©æä»¶");
|
| | | }
|
| | | // ä¸ä¼ æä»¶è·¯å¾
|
| | | String filePath = RuoYiConfig.getUploadPath();
|
| | | List<Map<String, String>> result = new ArrayList<>();
|
| | | for (MultipartFile file : files)
|
| | | {
|
| | | // ä¸ä¼ å¹¶è¿åæ°æä»¶åç§°
|
| | | String fileName = FileUploadUtils.upload(filePath, file);
|
| | | String url = serverConfig.getUrl() + fileName;
|
| | | Map<String, String> item = new LinkedHashMap<>();
|
| | | item.put("name", file.getOriginalFilename());
|
| | | item.put("url", url);
|
| | | result.add(item);
|
| | | }
|
| | | return AjaxResult.success(result);
|
| | | }
|
| | | catch (Exception e)
|
| | | {
|
| | | return AjaxResult.error(e.getMessage());
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * æ¬å°èµæºéç¨ä¸è½½
|
| | | */
|
| | | @GetMapping("/download/resource")
|
| | |
| | | */ |
| | | private Long productMainId; |
| | | |
| | | /** |
| | | * ç产工åid(æäº§ä¸è¾¾é¢çæè´¨æ£åç¨ï¼æ¤æ¶æ æ¥å·¥id) |
| | | */ |
| | | private Long workOrderId; |
| | | |
| | | private Long productModelId; |
| | | //ä¸åæ ¼ç°è±¡ |
| | | private String defectivePhenomena; |
| | |
| | | } else { |
| | | // è¿ç¨æ£éª/åºåæ£éªï¼éè¿å
³èå
³ç³»æ¥è¯¢éå®å°è´¦çå®¢æ· |
| | | customerValue = inspect.getCustomer(); // é»è®¤ä½¿ç¨ç´æ¥åå¨çå®¢æ· |
| | | Long workOrderId = inspect.getWorkOrderId(); |
| | | if (inspect.getProductMainId() != null) { |
| | | // éè¿æ¥å·¥IDæ¥è¯¢å·¥å |
| | | ProductionProductMain productMain = productionProductMainMapper.selectById(inspect.getProductMainId()); |
| | | if (productMain != null && productMain.getWorkOrderId() != null) { |
| | | ProductWorkOrder workOrder = productWorkOrderMapper.selectById(productMain.getWorkOrderId()); |
| | | if (workOrder != null && workOrder.getProductOrderId() != null) { |
| | | ProductOrder productOrder = productOrderMapper.selectById(workOrder.getProductOrderId()); |
| | | if (productOrder != null && productOrder.getSalesLedgerId() != null) { |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(productOrder.getSalesLedgerId()); |
| | | if (salesLedger != null && salesLedger.getCustomerName() != null) { |
| | | customerValue = salesLedger.getCustomerName(); |
| | | } |
| | | if (productMain != null) { |
| | | workOrderId = productMain.getWorkOrderId(); |
| | | } |
| | | } |
| | | if (workOrderId != null) { |
| | | ProductWorkOrder workOrder = productWorkOrderMapper.selectById(workOrderId); |
| | | if (workOrder != null && workOrder.getProductOrderId() != null) { |
| | | ProductOrder productOrder = productOrderMapper.selectById(workOrder.getProductOrderId()); |
| | | if (productOrder != null && productOrder.getSalesLedgerId() != null) { |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(productOrder.getSalesLedgerId()); |
| | | if (salesLedger != null && salesLedger.getCustomerName() != null) { |
| | | customerValue = salesLedger.getCustomerName(); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.production.pojo.*; |
| | | import com.ruoyi.production.service.ProductProcessService; |
| | | import com.ruoyi.production.service.ProductWorkOrderService; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | import com.ruoyi.production.service.impl.ProductOrderServiceImpl; |
| | | import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; |
| | | import com.ruoyi.purchase.pojo.PurchaseLedger; |
| | |
| | | |
| | | private final ProductWorkOrderService productWorkOrderService; |
| | | private final ProductProcessService productProcessService; |
| | | private ProductionProductMainService productionProductMainService; |
| | | private SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | private ProductionReportPersonMapper productionReportPersonMapper; |
| | | private SalesLedgerMapper salesLedgerMapper; |
| | | private PurchaseLedgerMapper purchaseLedgerMapper; |
| | | private ProductOrderMapper productOrderMapper; |
| | |
| | | productProcessRouteItem.setProductOrderId(productOrder.getId()); |
| | | productProcessRouteItem.setProductRouteId(productProcessRoute.getId()); |
| | | productProcessRouteItem.setDragSort(processRouteItem.getDragSort()); |
| | | productProcessRouteItem.setIsQuality(processRouteItem.getIsQuality()); |
| | | int insert = productProcessRouteItemMapper.insert(productProcessRouteItem); |
| | | if (insert > 0) { |
| | | ProductWorkOrder productWorkOrder = new ProductWorkOrder(); |
| | |
| | | } |
| | | |
| | | } |
| | | // æäº§ä¸è¾¾åèªå¨è§¦å第ä¸ééè´¨æ£å·¥åºçè¿ç¨æ£éª |
| | | productionProductMainService.preGenerateQualityInspectForOrder(productOrder.getId()); |
| | | productOrder.setRouteId(processRoute.getId()); |
| | | productOrderMapper.updateById(productOrder); |
| | | } |
| | |
| | | qualityInspectMapper.deleteByProductMainIds(productMainIds); |
| | | salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>() |
| | | .in(SalesLedgerProductionAccounting::getProductMainId, productMainIds)); |
| | | productionReportPersonMapper.delete(new LambdaQueryWrapper<ProductionReportPerson>() |
| | | .in(ProductionReportPerson::getProductMainId, productMainIds)); |
| | | } |
| | | |
| | | productionProductMainMapper.deleteByWorkOrderIds(workOrderIds); |
| | | // æ¸
çæäº§é¢çæçè´¨æ£å |
| | | productionProductMainService.cleanPreGeneratedQualityInspects(workOrderIds); |
| | | |
| | | productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .in(ProductWorkOrder::getProductOrderId, orderIds)); |
| | |
| | | druid: |
| | | # ä¸»åºæ°æ®æº |
| | | master: |
| | | url: jdbc:mysql://localhost:3300/product-inventory-management-ygcy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |
| | | url: jdbc:mysql://localhost:3306/product-inventory-management-ygcy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |
| | | username: root |
| | | password: root |
| | | password: 123456 |
| | | # ä»åºæ°æ®æº |
| | | slave: |
| | | # 仿°æ®æºå¼å
³/é»è®¤å
³é |
| | |
| | | database: 0 |
| | | # å¯ç |
| | | # password: root2022! |
| | | password: 123456 |
| | | # password: |
| | | |
| | | # è¿æ¥è¶
æ¶æ¶é´ |
| | | timeout: 10s |
| | |
| | | pp.name AS processName, |
| | | SUM(pi.quantity) AS totalInput, |
| | | SUM(distinct ppo.scrap_qty) AS totalScrap, |
| | | SUM(distinct (ppo.quantity - ppo.scrap_qty)) AS totalOutput |
| | | SUM(distinct (ppo.quantity + IFNULL(ppo.add_qty, 0))) AS totalOutput |
| | | FROM |
| | | production_product_output ppo |
| | | INNER JOIN production_product_main ppm ON ppo.product_main_id = ppm.id |
| | |
| | | END AS work_order_type, |
| | | pp.device_name, |
| | | pp.user_ids as process_user_ids, |
| | | t8.product_name as final_product_model |
| | | t8.product_name as final_product_model, |
| | | ppri.process_route_add_num as processRouteAddNum |
| | | FROM |
| | | product_work_order pwo |
| | | LEFT JOIN product_process_route_item ppri ON ppri.id = pwo.product_process_route_item_id |
| | |
| | | sum(ppo.scrap_qty) scrapQty, |
| | | pp.device_id, |
| | | pp.device_name, |
| | | t8.product_name as final_product_model |
| | | t8.product_name as final_product_model, |
| | | ppri.process_route_add_num as processRouteAddNum |
| | | FROM |
| | | product_work_order pwo |
| | | LEFT JOIN product_process_route_item ppri ON ppri.id = pwo.product_process_route_item_id |
| | |
| | | pm.model, |
| | | pm.unit, |
| | | p.product_name, |
| | | po.nps_no |
| | | po.nps_no, |
| | | ppri.process_route_add_num |
| | | </select> |
| | | <select id="selectWorkOrderStartStats" resultType="com.ruoyi.production.dto.ProductWorkOrderDto"> |
| | | SELECT |
| | |
| | | pm.model as product_model_name, |
| | | pm.unit, |
| | | slpa.process, |
| | | ppo.quantity, |
| | | COALESCE(prp.quantity, slpa.finished_num) AS quantity, |
| | | slpa.work_hours, |
| | | slpa.work_hours * slpa.finished_num AS wages, |
| | | dl.device_name, |
| | | slpa.work_hour as work_minutes, |
| | | slpa.work_hour as person_work_minutes, |
| | | IFNULL( |
| | | TIMESTAMPDIFF(MINUTE, ppm.start_time, ppm.end_time), |
| | | 0 |
| | |
| | | FROM |
| | | production_product_main ppm |
| | | LEFT JOIN sales_ledger_production_accounting slpa ON slpa.product_main_id = ppm.id |
| | | LEFT JOIN production_report_person prp ON prp.product_main_id = ppm.id AND prp.user_id = slpa.scheduling_user_id |
| | | LEFT JOIN production_product_output ppo ON ppm.id = ppo.product_main_id |
| | | LEFT JOIN product_work_order pwo ON pwo.id = ppm.work_order_id |
| | | LEFT JOIN product_order po ON po.id = pwo.product_order_id |
| | |
| | | <select id="selectDailyOutputStats" resultType="java.util.Map"> |
| | | SELECT |
| | | DATE_FORMAT(create_time, '%Y-%m-%d') as date, |
| | | SUM(quantity-scrap_qty) as quantity |
| | | SUM(quantity + IFNULL(add_qty, 0)) as quantity |
| | | FROM |
| | | production_product_output |
| | | WHERE |
| | |
| | | |
| | | SELECT |
| | | slpa.scheduling_user_name, |
| | | SUM(ppout.quantity) AS output_num, |
| | | SUM(COALESCE(prp.quantity, slpa.finished_num)) AS output_num, |
| | | CONCAT( |
| | | ROUND( |
| | | CASE |
| | |
| | | FROM sales_ledger_production_accounting slpa |
| | | LEFT JOIN production_product_main ppm |
| | | ON slpa.product_main_id = ppm.id |
| | | LEFT JOIN production_report_person prp |
| | | ON prp.product_main_id = ppm.id AND prp.user_id = slpa.scheduling_user_id |
| | | LEFT JOIN production_product_output ppout |
| | | ON ppm.id = ppout.product_main_id |
| | | left join device_ledger dl on dl.id = slpa.device_id |
| | |
| | | |
| | | <select id="selectDailyWagesStats" resultType="java.util.Map"> |
| | | SELECT DATE(ppout.create_time) AS dateStr, |
| | | SUM(ppout.quantity - IFNULL(ppout.scrap_qty, 0)) AS numberOfCompleted, |
| | | SUM((ppout.quantity - IFNULL(ppout.scrap_qty, 0)) * IFNULL(pp.salary_quota, 0)) AS amount, |
| | | SUM(ppout.quantity + IFNULL(ppout.add_qty, 0) - IFNULL(ppout.scrap_qty, 0)) AS numberOfCompleted, |
| | | SUM((ppout.quantity + IFNULL(ppout.add_qty, 0) - IFNULL(ppout.scrap_qty, 0)) * IFNULL(pp.salary_quota, 0)) AS amount, |
| | | ROUND( |
| | | SUM(ppout.quantity - IFNULL(ppout.scrap_qty, 0)) * 100 / NULLIF(SUM(ppout.quantity), 0), |
| | | SUM(ppout.quantity + IFNULL(ppout.add_qty, 0) - IFNULL(ppout.scrap_qty, 0)) * 100 / NULLIF(SUM(ppout.quantity), 0), |
| | | 2 |
| | | ) AS passRate |
| | | FROM production_product_output ppout |
| | |
| | | </when> |
| | | <otherwise> |
| | | LEFT JOIN production_product_main ppm ON qi.product_main_id = ppm.id |
| | | LEFT JOIN product_work_order pwo ON ppm.work_order_id = pwo.id |
| | | LEFT JOIN product_work_order pwo ON pwo.id = COALESCE(qi.work_order_id, ppm.work_order_id) |
| | | </otherwise> |
| | | </choose> |
| | | WHERE |
| | |
| | | </when> |
| | | <otherwise> |
| | | LEFT JOIN production_product_main ppm ON qi.product_main_id = ppm.id |
| | | LEFT JOIN product_work_order pwo ON ppm.work_order_id = pwo.id |
| | | LEFT JOIN product_work_order pwo ON pwo.id = COALESCE(qi.work_order_id, ppm.work_order_id) |
| | | </otherwise> |
| | | </choose> |
| | | WHERE qi.inspect_type=#{qualityInspect.inspectType} |