Merge remote-tracking branch 'origin/dev_New_pro' into dev_New_pro
# Conflicts:
# src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æä»¶ä¸ä¼ åè½è¯´æ |
| | | |
| | | æ¬ææ¡£åºäºä»¥ä¸ä»£ç æ´çï¼ |
| | | |
| | | - `src/main/java/com/ruoyi/basic/utils/FileUtil.java` |
| | | - `src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java` |
| | | - `src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java` |
| | | - `src/main/java/com/ruoyi/project/common/CommonController.java` |
| | | - `src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java` |
| | | |
| | | ç¨äºè¯´ææ¬é¡¹ç®ä¸æä»¶ä¸ä¼ ãéä»¶ç»å®ãæä»¶é¢è§/ä¸è½½çæ´ä½è®¾è®¡ï¼ä»¥å `FileUtil` 䏿¯ä¸ªæ¹æ³çä½ç¨ã |
| | | |
| | | ## 1. æ´ä½è®¾è®¡ |
| | | |
| | | æ¬é¡¹ç®çæä»¶ä½ç³»åæä¸¤å±ï¼ |
| | | |
| | | - `storage_blob`ï¼åæä»¶å®ä½ä¿¡æ¯ |
| | | - åå§æä»¶å |
| | | - å¯ä¸æä»¶å `uidFilename` |
| | | - æä»¶è·¯å¾ `path` |
| | | - æä»¶å¤§å° `byteSize` |
| | | - æä»¶ç±»å `contentType` |
| | | - å
Œ
±è®¿é®æ è¯ `resourceKey` |
| | | - `storage_attachment`ï¼åæä»¶åä¸å¡è®°å½çå
³èå
³ç³» |
| | | - `application`ï¼æä»¶ç¨é |
| | | - `recordType`ï¼ä¸å¡è®°å½ç±»å |
| | | - `recordId`ï¼ä¸å¡è®°å½ä¸»é® |
| | | - `storageBlobId`ï¼å
³èçæä»¶ä¸»è¡¨ id |
| | | |
| | | å¯ä»¥çè§£ä¸ºï¼ |
| | | |
| | | - `storage_blob` è´è´£âæä»¶æ¬èº«â |
| | | - `storage_attachment` è´è´£âæä»¶æå¨åªæ¡ä¸å¡æ°æ®ä¸â |
| | | |
| | | ## 2. ä¸ä¼ æµç¨ |
| | | |
| | | ### 2.1 æ®éä¸ä¼ |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `POST /common/upload` |
| | | |
| | | æ§å¶å¨ä½ç½®ï¼ |
| | | |
| | | - `src/main/java/com/ruoyi/project/common/CommonController.java` |
| | | |
| | | å
¥åï¼ |
| | | |
| | | - 表ååæ®µåï¼`files` |
| | | - ç±»åï¼`List<MultipartFile>` |
| | | |
| | | 代ç é»è¾ï¼ |
| | | |
| | | 1. å端å
è°ç¨ `/common/upload` |
| | | 2. `CommonController.upload()` è°ç¨ `storageBlobService.upload(files, false)` |
| | | 3. æå¡å±ä¿åæä»¶å
æ°æ®å° `storage_blob` |
| | | 4. è¿å `StorageBlobVO` å表ï¼éé¢é常ä¼å¸¦ï¼ |
| | | - æä»¶ id |
| | | - åå§æä»¶å |
| | | - å¯ä¸æä»¶å |
| | | - é¢è§å°å `previewURL` |
| | | - ä¸è½½å°å `downloadURL` |
| | | |
| | | 说æï¼ |
| | | |
| | | - æ¤æ¶åªæ¯âä¸ä¼ äºæä»¶â |
| | | - è¿æ²¡æåå
·ä½ä¸å¡åæ®å»ºç«å
³ç³» |
| | | |
| | | ### 2.2 å
Œ
±ä¸ä¼ |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `POST /common/public/upload` |
| | | |
| | | 代ç é»è¾ï¼ |
| | | |
| | | - `CommonController.publicUpload()` è°ç¨ `storageBlobService.upload(files, true)` |
| | | |
| | | 说æï¼ |
| | | |
| | | - 该æ¥å£ä¸ä¼ çæä»¶èµ°âå
Œ
±æä»¶âæ¨¡å¼ |
| | | - æ§å¶å¨æ³¨éå·²æç¡®è¯´æï¼æ°¸ä¹
ææï¼æ
ç¨ |
| | | - å¯¹åº URL æå»ºæ¶ï¼å¯è½èµ° `publicKey` åæ°ï¼è䏿¯ä¸´æ¶ `token` |
| | | |
| | | ## 3. éä»¶ç»å®æµç¨ |
| | | |
| | | ä¸ä¼ 宿åï¼å¦æéè¦ææä»¶ç»å®å°ææ¡ä¸å¡è®°å½ï¼éè¦åè°ç¨éä»¶æ¥å£ã |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `POST /storageAttachment/add` |
| | | |
| | | æ§å¶å¨ä½ç½®ï¼ |
| | | |
| | | - `src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java` |
| | | |
| | | æ ¸å¿è¯·æ±å¯¹è±¡ï¼ |
| | | |
| | | - `StorageAttachmentDTO` |
| | | |
| | | å
¶ä¸ç»§æ¿äº `StorageAttachment`ï¼å¹¶é¢å¤å
å«ï¼ |
| | | |
| | | - `storageBlobDTOs`ï¼å¾
ç»å®çæä»¶å表 |
| | | |
| | | 常ç¨å段å«ä¹ï¼ |
| | | |
| | | - `application`ï¼æä»¶ç¨é |
| | | - `recordType`ï¼ä¸å¡ç±»å |
| | | - `recordId`ï¼ä¸å¡ä¸»é® |
| | | - `storageBlobDTOs[].id`ï¼ä¸ä¼ æååè¿åçæä»¶ id |
| | | |
| | | 示ä¾è¯·æ±ä½ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "application": "file", |
| | | "recordType": "common_file", |
| | | "recordId": 1001, |
| | | "storageBlobDTOs": [ |
| | | { |
| | | "id": 12, |
| | | "application": "file" |
| | | }, |
| | | { |
| | | "id": 13, |
| | | "application": "file" |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | ç»å®é»è¾è¯´æï¼ |
| | | |
| | | 1. å
ä¸ä¼ æä»¶ï¼æ¿å° `storage_blob.id` |
| | | 2. åè°ç¨ `/storageAttachment/add` |
| | | 3. æå¡å±æç»ä¼éè¿ `FileUtil` ä¿å `storage_attachment` |
| | | 4. åç»å³å¯æä¸å¡è®°å½æ¥è¯¢åºè¯¥è®°å½ä¸çéä»¶ |
| | | |
| | | ## 4. æ¥è¯¢ä¸å é¤éä»¶ |
| | | |
| | | ### 4.1 æ¥è¯¢éä»¶å表 |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `GET /storageAttachment/list` |
| | | |
| | | 说æï¼ |
| | | |
| | | - æ `StorageAttachmentDTO` ä¸çæ¡ä»¶æ¥è¯¢ |
| | | - å¸¸è§æ¡ä»¶æ¯ `application`ã`recordType`ã`recordId` |
| | | - è¿åç»ææ¬è´¨ä¸æ¯åä¸å¡è®°å½å
³èåçæä»¶å表 |
| | | |
| | | ### 4.2 å é¤éä»¶ |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `DELETE /storageAttachment/delete` |
| | | |
| | | 请æ±ä½ï¼ |
| | | |
| | | - `List<Long> ids` |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¿éç `ids` æ¯éä»¶å
³è表 idï¼ä¸è¬æ¯ `storage_attachment.id` |
| | | - å 餿¶é常ä¸ä»
ä¼å å
³èå
³ç³»ï¼ä¹ä¼è¿ä¸æ¥å é¤å¯¹åºæä»¶è®°å½ |
| | | |
| | | ## 5. é¢è§ä¸ä¸è½½æµç¨ |
| | | |
| | | ### 5.1 ä¸è½½æ¥å£ |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `GET /common/download/{fileName}` |
| | | |
| | | æ¯æä¸¤ç§è®¿é®æ¹å¼ï¼ |
| | | |
| | | - 临æ¶é¾æ¥ï¼`token` |
| | | - å
Œ
±é¾æ¥ï¼`publicKey` |
| | | |
| | | 代ç é»è¾ï¼ |
| | | |
| | | 1. å¦æè¯·æ±éæ `publicKey`ï¼èµ° `storageBlobService.getPublicFile(fileName, publicKey)` |
| | | 2. å¦åèµ° `storageBlobService.getFileByToken(fileName, token)` |
| | | 3. åå°å®é
æä»¶åï¼è°ç¨ `fileUtil.compressFile(file)` åå¾çå缩å¤ç |
| | | 4. 设置ä¸è½½ååºå¤´ï¼è¾åºæä»¶æµ |
| | | |
| | | ### 5.2 é¢è§æ¥å£ |
| | | |
| | | æ¥å£ï¼ |
| | | |
| | | - `GET /common/preview/{fileName}` |
| | | |
| | | æ¯æä¸¤ç§è®¿é®æ¹å¼ï¼ |
| | | |
| | | - 临æ¶é¾æ¥ï¼`token` |
| | | - å
Œ
±é¾æ¥ï¼`publicKey` |
| | | |
| | | 代ç é»è¾ï¼ |
| | | |
| | | 1. æ ¡éª `token` æ `publicKey` |
| | | 2. è·åæä»¶ |
| | | 3. è°ç¨ `fileUtil.compressFile(file)` |
| | | 4. æ ¹æ®æä»¶å
容类åè¿å inline é¢è§ |
| | | |
| | | ## 6. æä¸¾å«ä¹ |
| | | |
| | | ### 6.1 `ApplicationTypeEnum` |
| | | |
| | | ä½ç½®ï¼ |
| | | |
| | | - `src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java` |
| | | |
| | | å½åå®ä¹å¼ï¼ |
| | | |
| | | | æä¸¾ | type | 说æ | |
| | | |---|---|---| |
| | | | `IMAGE` | `image` | å¾çç±»æä»¶ | |
| | | | `FILE` | `file` | æ®éæä»¶ | |
| | | | `AFTER_FILE` | `after_file` | å®åç¸å
³æä»¶ | |
| | | | `BEFORE_FILE` | `before_file` | å®å/åç½®ç¸å
³æä»¶ | |
| | | | `APK` | `apk` | å®è£
å
æä»¶ | |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - ç¨äºåºåå䏿¡ä¸å¡è®°å½ä¸ï¼ä¸åç¨éçæä»¶ |
| | | - `FileUtil` çå¾å¤æ¥è¯¢ãå é¤ãä¿åæ¹æ³é½ä¼ç¨å°è¯¥å段 |
| | | |
| | | ### 6.2 `RecordTypeEnum` |
| | | |
| | | ä½ç½®ï¼ |
| | | |
| | | - `src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - ç¨äºæ è®°æä»¶å±äºåªç±»ä¸å¡è®°å½ |
| | | - ä¾å¦è´¨æ£ãéè´ã客æ·ãå®åãå°è´¦ãéç¥ã设å¤ç模å |
| | | - ä¸ä¼ 宿åï¼éä»¶æç»éè¿ `recordType + recordId` åä¸å¡æ°æ®å
³è |
| | | |
| | | 说æï¼ |
| | | |
| | | - 该æä¸¾å¼å¾å¤ï¼ææ¡£ä¸é个å±å¼ |
| | | - å®é
ä½¿ç¨æ¶å¿
é¡»ä¼ ä»£ç ä¸å·²å®ä¹ç `type` å¼ |
| | | - å¦ï¼ |
| | | - `common_file` |
| | | - `after_sales_service` |
| | | - `quality_inspect` |
| | | - `product` |
| | | - `notice` |
| | | |
| | | ## 7. `FileUtil` æ¹æ³è¯´æ |
| | | |
| | | `FileUtil` æ¯æ¬å¥æä»¶ä¸ä¼ ä½ç³»çæ ¸å¿å·¥å
·ç±»ï¼ä¸»è¦è´è´£ï¼ |
| | | |
| | | - æä»¶ä¸ä¸å¡è®°å½ç»å® |
| | | - æä»¶ä¸éä»¶å é¤ |
| | | - éä»¶æ¥è¯¢ |
| | | - é¢è§/ä¸è½½å°åçæ |
| | | - token ä½¿ç¨æ¬¡æ°æ§å¶ |
| | | - å¾çå缩 |
| | | |
| | | ä¸é¢æåè½åç»è¯´ææ¯ä¸ªæ¹æ³ã |
| | | |
| | | ### 7.1 ä¿åéä»¶å
³ç³» |
| | | |
| | | #### 1. `saveStorageAttachment(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æâæä»¶ç¨é + è®°å½ç±»å + è®°å½ idâä¿åéä»¶å
³ç³» |
| | | |
| | | é»è¾ï¼ |
| | | |
| | | 1. æ ¡éª `application`ã`recordType`ã`recordId` |
| | | 2. å
å é¤è¿ç»ä¸å¡è®°å½ä¸çæ§éä»¶ |
| | | 3. ææ°ç `storageBlobDTOS` 转æ `storage_attachment` è®°å½åæ¹éæå
¥ |
| | | |
| | | éç¨åºæ¯ï¼ |
| | | |
| | | - ææ¡ä¸å¡æ°æ®éæ°ä¿åéä»¶ï¼æ§éä»¶æ´ä½æ¿æ¢ææ°éä»¶ |
| | | |
| | | #### 2. `saveStorageAttachmentByRecordTypeAndRecordId(String application, RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ `recordType + recordId` ä¿åéä»¶å
³ç³»ï¼`application` 坿å®ï¼ä¹å¯ä»æ¯ä¸ªæä»¶å¯¹è±¡é读å |
| | | |
| | | é»è¾ç¹ç¹ï¼ |
| | | |
| | | - 妿 `application == null`ï¼ä¼æ ¹æ® `storageBlobDTO.application` åå«å 餿§å
³ç³» |
| | | - 妿éä»¶å表为空ï¼ä¼ç´æ¥å é¤è¯¥ä¸å¡è®°å½çéä»¶å
³ç³» |
| | | - æå
¥æ¶ä¼èªå¨åå¡« `application` |
| | | |
| | | éç¨åºæ¯ï¼ |
| | | |
| | | - 䏿¬¡æäº¤éå¯è½å
å«å¤ç§ç¨éçéä»¶ |
| | | - æè
è°ç¨æ¹ä¸æ¹ä¾¿ç´æ¥ä¼ æä¸¾ç±»å |
| | | |
| | | ### 7.2 å é¤æä»¶ä¸»è¡¨ `storage_blob` |
| | | |
| | | #### 3. `deleteStorageBlobs(List<Long> storageBlobIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - ææä»¶ä¸»è¡¨ id æ¹éå é¤æä»¶è®°å½ |
| | | |
| | | #### 4. `deleteStorageBlobsByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - å
æ ¹æ®éä»¶å
³è id æ¥å° `storageBlobId` |
| | | - åå é¤å¯¹åºçæä»¶ä¸»è¡¨è®°å½ |
| | | |
| | | #### 5. `deleteStorageBlobsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®ç¨éãè®°å½ç±»åãå¤ä¸ªä¸å¡ idï¼æ¹éå é¤å¯¹åºçæä»¶ä¸»è¡¨è®°å½ |
| | | |
| | | éç¨åºæ¯ï¼ |
| | | |
| | | - æ¹éå é¤æç±»ä¸å¡æ°æ®æ¶ï¼åæ¶æ¸
çéä»¶ |
| | | |
| | | #### 6. `deleteStorageBlobsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ® `recordType + recordId` å é¤è¯¥ä¸å¡è®°å½ä¸æææä»¶ä¸»è¡¨è®°å½ |
| | | |
| | | ### 7.3 å é¤éä»¶å
³ç³» `storage_attachment` |
| | | |
| | | #### 7. `deleteStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - å
å é¤é件对åºçæä»¶ä¸»è¡¨è®°å½ |
| | | - åå é¤éä»¶å
³ç³»è¡¨è®°å½ |
| | | |
| | | #### 8. `deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - å 餿å®ç¨éãæå®ä¸å¡è®°å½ä¸çéä»¶å
³ç³» |
| | | |
| | | ç¹ç¹ï¼ |
| | | |
| | | - ä¼å
å blobï¼åå attachment |
| | | |
| | | #### 9. `deleteStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - å 餿å®ä¸å¡è®°å½ä¸å
¨é¨éä»¶å
³ç³»ï¼ä¸åºåç¨é |
| | | |
| | | #### 10. `deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æå¤ä¸ªä¸å¡ id æ¹éå é¤éä»¶å
³ç³» |
| | | |
| | | ### 7.4 æ¥è¯¢éä»¶å
³ç³» |
| | | |
| | | #### 11. `getStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id æ¥è¯¢ `storage_attachment` è®°å½ |
| | | |
| | | #### 12. `getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æç¨éãä¸å¡ç±»åãä¸å¡ id æ¥è¯¢éä»¶å
³ç³» |
| | | |
| | | #### 13. `getStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç±»åãä¸å¡ id æ¥è¯¢éä»¶å
³ç³» |
| | | |
| | | ### 7.5 æ¥è¯¢æä»¶ä¿¡æ¯ `StorageBlobVO` |
| | | |
| | | #### 14. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(StorageAttachmentDTO storageAttachmentDTO)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - éè¿ `StorageAttachmentDTO` æ¡ä»¶æ¥è¯¢æä»¶å表 |
| | | |
| | | ç¹ç¹ï¼ |
| | | |
| | | - `application` å¯é |
| | | - æç»è¿åçæ¯å¸¦é¢è§/ä¸è½½å°åç `StorageBlobVO` |
| | | |
| | | #### 15. `getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id æ¥è¯¢æä»¶å表 |
| | | |
| | | ç¹ç¹ï¼ |
| | | |
| | | - ä¼èªå¨æå»ºï¼ |
| | | - `previewURL` |
| | | - `downloadURL` |
| | | - `storageAttachmentId` |
| | | |
| | | #### 16. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æç¨éãä¸å¡ç±»åãä¸å¡ id æ¥è¯¢æä»¶å表 |
| | | |
| | | #### 17. `getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç±»åãä¸å¡ id æ¥è¯¢æä»¶å表 |
| | | |
| | | #### 18. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - å第 16 ä¸ªæ¹æ³ç±»ä¼¼ï¼ä½å¯ä»¥èªå®ä¹é¾æ¥è¿ææ¶é´ |
| | | |
| | | 说æï¼ |
| | | |
| | | - `expired` å使¯åé |
| | | - è¿åçé¢è§/ä¸è½½å°å伿è¿ä¸ªæ¶é´çæç¾å |
| | | |
| | | #### 19. `getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id æ¥è¯¢æä»¶å表ï¼å¹¶èªå®ä¹é¾æ¥è¿ææ¶é´ |
| | | |
| | | ### 7.6 æ¥è¯¢éä»¶è§å¾ `StorageAttachmentVO` |
| | | |
| | | #### 20. `getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ¥è¯¢éä»¶è§å¾å¯¹è±¡ |
| | | |
| | | ç¹ç¹ï¼ |
| | | |
| | | - æ¯æ¡éä»¶è®°å½éä¼åµå¥èªå·±ç `storageBlobVOS` |
| | | |
| | | #### 21. `getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id æ¥è¯¢éä»¶è§å¾ï¼å¹¶èªå®ä¹é¾æ¥è¿ææ¶é´ |
| | | |
| | | #### 22. `getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦æ¥è¯¢éä»¶è§å¾ |
| | | |
| | | #### 23. `getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦æ¥è¯¢éä»¶è§å¾ï¼å¹¶èªå®ä¹é¾æ¥è¿ææ¶é´ |
| | | |
| | | ### 7.7 ä»
è·åé¢è§å°å |
| | | |
| | | #### 24. `getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id å表ï¼è¿åé¢è§å°åå表 |
| | | |
| | | #### 25. `getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id å表ï¼è¿å带èªå®ä¹è¿ææ¶é´çé¢è§å°åå表 |
| | | |
| | | #### 26. `getFilePreviewURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦è¿åé¢è§å°åå表 |
| | | |
| | | #### 27. `getFilePreviewURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦è¿å带èªå®ä¹è¿ææ¶é´çé¢è§å°åå表 |
| | | |
| | | ### 7.8 ä»
è·åä¸è½½å°å |
| | | |
| | | #### 28. `getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id å表ï¼è¿åä¸è½½å°åå表 |
| | | |
| | | #### 29. `getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¹æ®éä»¶å
³ç³» id å表ï¼è¿å带èªå®ä¹è¿ææ¶é´çä¸è½½å°åå表 |
| | | |
| | | #### 30. `getFileDownloadURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦è¿åä¸è½½å°åå表 |
| | | |
| | | #### 31. `getFileDownloadURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æä¸å¡ç»´åº¦è¿å带èªå®ä¹è¿ææ¶é´çä¸è½½å°åå表 |
| | | |
| | | ### 7.9 æå»ºç¾å URL |
| | | |
| | | #### 32. `buildSignedPreviewUrl(StorageBlobVO storageBlob)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - 使ç¨ç³»ç»é»è®¤è¿ææ¶é´ï¼çæé¢è§é¾æ¥ |
| | | |
| | | å®é
è°ç¨ï¼ |
| | | |
| | | - å
é¨çä»·äºè°ç¨ `buildSignedUrl(storageBlob, "/preview/", properties.getExpired())` |
| | | |
| | | #### 33. `buildSignedDownloadUrl(StorageBlobVO storageBlob)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - 使ç¨ç³»ç»é»è®¤è¿ææ¶é´ï¼çæä¸è½½é¾æ¥ |
| | | |
| | | å®é
è°ç¨ï¼ |
| | | |
| | | - å
é¨çä»·äºè°ç¨ `buildSignedUrl(storageBlob, "/download/", properties.getExpired())` |
| | | |
| | | #### 34. `buildSignedUrl(StorageBlobVO storageBlob, String actionPath, BigDecimal expired)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æå»ºç»ä¸ç带ç¾åé¢è§/ä¸è½½å°å |
| | | |
| | | æ¯æï¼ |
| | | |
| | | - `actionPath = "/preview/"` |
| | | - `actionPath = "/download/"` |
| | | |
| | | æ ¸å¿é»è¾ï¼ |
| | | |
| | | 1. æ ¡éªè·¯å¾åæ°åæä»¶ä¿¡æ¯ |
| | | 2. æ¼æ¥åºç¡è®¿é®å°å |
| | | 3. 妿 `expired == -1`ï¼ä¸çæ tokenï¼ç´æ¥èµ° `publicKey` |
| | | 4. å¦åçæå¸¦è¿ææ¶é´ç JWT token |
| | | 5. æ token çä½¿ç¨æ¬¡æ°ä¿¡æ¯åå
¥ Redis |
| | | 6. è¿åæç» URL |
| | | |
| | | éè¦è¯´æï¼ |
| | | |
| | | - `expired` åä½ä¸ºåé |
| | | - é»è®¤è¿ææ¶é´ä¸º 120 åé |
| | | - éæ°¸ä¹
龿¥ä¼åâè¿ææ¶é´ + ä½¿ç¨æ¬¡æ°éå¶âåéæ§å¶ |
| | | |
| | | ### 7.10 token ä½¿ç¨æ§å¶ |
| | | |
| | | #### 35. `cacheTokenUsage(String token, long expiredMillis)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ token ä½¿ç¨æ¬¡æ°åå§åå° Redis |
| | | |
| | | ç¹ç¹ï¼ |
| | | |
| | | - åå§å¼åå
¥ä¸º `0` |
| | | - TTL ä¸ token è¿ææ¶é´ä¿æä¸è´ |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¿æ¯ç§ææ¹æ³ï¼ä¾ `buildSignedUrl()` å
é¨è°ç¨ |
| | | |
| | | #### 36. `buildTokenUsageKey(String token)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - ç»ä¸çæ Redis key |
| | | |
| | | æ ¼å¼ï¼ |
| | | |
| | | - `file:token:usage:{token}` |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¿æ¯ç§ææ¹æ³ |
| | | |
| | | #### 37. `validateTokenUsage(String token)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - æ ¡éª token æ¯å¦è¿è½ç»§ç»ä½¿ç¨ |
| | | |
| | | æ ¸å¿é»è¾ï¼ |
| | | |
| | | 1. ä» Redis 读åå½åä½¿ç¨æ¬¡æ° |
| | | 2. å¦ææ²¡æå¼ï¼è®¤ä¸ºé¾æ¥å·²è¿ææå·²å¤±æ |
| | | 3. å¦æè¾¾å°ä¸éï¼ç«å³å é¤ Redis è®°å½å¹¶æ¥é |
| | | 4. å¦åèªå¢ä¸æ¬¡ä½¿ç¨æ¬¡æ° |
| | | 5. 妿èªå¢åè¾¾å°ä¸éï¼åå é¤ Redis è®°å½ |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¯¥æ¹æ³é常ä¼å¨å®é
è®¿é®æä»¶æ¶ç±æå¡å±è°ç¨ |
| | | |
| | | #### 38. `resolveLimit()` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - è§£æ token å¯ä½¿ç¨æ¬¡æ°ä¸é |
| | | |
| | | è§åï¼ |
| | | |
| | | - `properties.getUseLimit() <= 0` æ¶ï¼é»è®¤è¿å `10` |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¿æ¯ç§ææ¹æ³ |
| | | |
| | | ### 7.11 è·¯å¾ä¸å缩 |
| | | |
| | | #### 39. `buildRelativePath()` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - çææä»¶åå¨ç¸å¯¹è·¯å¾ |
| | | |
| | | æ ¼å¼ï¼ |
| | | |
| | | - `yyyy/MMdd` |
| | | |
| | | ä¾å¦ï¼ |
| | | |
| | | - `2026/0430` |
| | | |
| | | ç¨éï¼ |
| | | |
| | | - ä¸è¬ç¨äºææ¥æåç®å½ä¿åä¸ä¼ æä»¶ |
| | | |
| | | #### 40. `compressFile(File file)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - 对å¾çè¿è¡å缩ï¼éå¾çæä¸æ»¡è¶³æ¡ä»¶æ¶è¿ååæä»¶ |
| | | |
| | | å缩æ¡ä»¶ï¼ |
| | | |
| | | 1. å¼å¯äº `properties.getCompress()` |
| | | 2. æä»¶æ¯å¾ç |
| | | 3. æä»¶å¤§å°å¤§äº `properties.getNeedCompressSize()` |
| | | |
| | | å¤çé»è¾ï¼ |
| | | |
| | | 1. ç®æ æä»¶å为 `thumb_åæä»¶å` |
| | | 2. 妿å缩æä»¶å·²åå¨ï¼ç´æ¥å¤ç¨ |
| | | 3. ä½¿ç¨ `Thumbnailator` æå尺寸å缩ç»è´¨ |
| | | 4. 妿å缩失败ï¼é级è¿ååæä»¶ |
| | | |
| | | 说æï¼ |
| | | |
| | | - å½åä¸è½½åé¢è§æ¥å£é½ä¼è°ç¨è¿ä¸ªæ¹æ³ |
| | | |
| | | #### 41. `isImage(String fileName)` |
| | | |
| | | ä½ç¨ï¼ |
| | | |
| | | - ç®å夿æä»¶æ¯å¦æ¯å¾ç |
| | | |
| | | æ¯æåç¼ï¼ |
| | | |
| | | - `jpg` |
| | | - `jpeg` |
| | | - `png` |
| | | |
| | | 说æï¼ |
| | | |
| | | - è¿æ¯ç§ææ¹æ³ï¼ä¾ `compressFile()` ä½¿ç¨ |
| | | |
| | | ## 8. æ¨è使ç¨é¡ºåº |
| | | |
| | | ä¸å¡ä¸æå¸¸è§çæ¥å
¥é¡ºåºå¦ä¸ï¼ |
| | | |
| | | 1. å端ä¸ä¼ æä»¶å° `/common/upload` |
| | | 2. æ¿å°è¿åç»æä¸çæä»¶ id |
| | | 3. ä¸å¡ä¿åæ¶è°ç¨ `/storageAttachment/add` |
| | | 4. ä¼ å
¥ `application + recordType + recordId + storageBlobDTOs` |
| | | 5. åç»é¡µé¢åæ¾æ¶æä¸å¡æ¡ä»¶è°ç¨éä»¶æ¥è¯¢ |
| | | 6. å端使ç¨è¿åç `previewURL` æ `downloadURL` |
| | | |
| | | ## 9. å¸¸è§æ³¨æç¹ |
| | | |
| | | ### 9.1 å
ä¸ä¼ ï¼åç»å® |
| | | |
| | | - `/common/upload` åªè´è´£æä»¶å
¥åº |
| | | - `/storageAttachment/add` ææ¯åä¸å¡æ°æ®å»ºç«å
³ç³» |
| | | |
| | | ### 9.2 `application` å¾éè¦ |
| | | |
| | | - å䏿¡ `recordId` ä¸å¯è½æå¤ç»ä¸åç¨ééä»¶ |
| | | - å é¤åæ¥è¯¢æ¶ï¼ç»å¸¸ä¾èµ `application` |
| | | |
| | | ### 9.3 ä¸è½½é¾æ¥ä¸æ¯æ°¸ä¹
ææ |
| | | |
| | | - æ®é龿¥ä¸è¬éè¿ JWT token æ§å¶ |
| | | - åæ¶åè¿ææ¶é´åä½¿ç¨æ¬¡æ°éå¶ |
| | | |
| | | ### 9.4 å
Œ
±æä»¶è¦æ
ç¨ |
| | | |
| | | - `public/upload` ä¸ä¼ çæä»¶å¯èµ°æ°¸ä¹
å
¬å¼è®¿é® |
| | | - éåå
¬å¼èµæºï¼ä¸éåæææä»¶ |
| | | |
| | | ### 9.5 å¾çé¢è§/ä¸è½½å¯è½è¿åå缩æä»¶ |
| | | |
| | | - å½åæ§å¶å¨å¨ä¸è½½åé¢è§åé½ä¼è°ç¨ `compressFile()` |
| | | - 大å¾å¨è®¿é®æ¶å¯è½ä½¿ç¨å缩åç坿¬ |
| | | |
| | | ## 10. ä¸å¥è¯æ»ç» |
| | | |
| | | æ¬é¡¹ç®çæä»¶ä¸ä¼ æ¹æ¡æ¯â䏤鶿®µæ¨¡åâï¼ |
| | | |
| | | - 第ä¸é¶æ®µä¸ä¼ æä»¶ï¼çæ `storage_blob` |
| | | - 第äºé¶æ®µç»å®ä¸å¡ï¼çæ `storage_attachment` |
| | | |
| | | è `FileUtil` åè´è´£æâä¸ä¼ åçæä»¶âåæâ坿¥è¯¢ãå¯é¢è§ãå¯ä¸è½½ãå¯å é¤ã坿§æ¶æâç宿´éä»¶è½åã |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.approve.vo.ApproveProcessVo; |
| | | import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessVO; |
| | |
| | | import com.ruoyi.approve.service.ApproveProcessConfigNodeService; |
| | | import com.ruoyi.approve.service.IApproveNodeService; |
| | | import com.ruoyi.approve.service.IApproveProcessService; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.approve.vo.ApproveProcessVo; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | |
| | | .map(ApproveProcessConfigNodeVo::getApproverId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if(list.isEmpty()) { |
| | | throw new RuntimeException("æµç¨ä¸åå¨"); |
| | | } |
| | | if (CollectionUtils.isEmpty(nodeIds)) { |
| | | autoPassPurchaseApproveIfNoApprover(approveProcessVO); |
| | | return; |
| | |
| | | package com.ruoyi.basic.controller; |
| | | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.basic.dto.StorageAttachmentDTO; |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import com.ruoyi.basic.dto.SupplierManageDto; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.pojo.StorageAttachment; |
| | | import com.ruoyi.basic.service.StorageAttachmentService; |
| | | import com.ruoyi.common.constant.StorageAttachmentConstants; |
| | | import com.ruoyi.common.enums.StorageAttachmentRecordType; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | |
| | | @RestController |
| | | @AllArgsConstructor |
| | | @RequestMapping("/basic/storage_attachment") |
| | | @Tag(name = "éç¨ä¸ä¼ ") |
| | | @RequestMapping("/storageAttachment") |
| | | public class StorageAttachmentController { |
| | | private StorageAttachmentService storageAttachmentService; |
| | | |
| | | /** |
| | | * å页æ¥è¯¢éç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯ |
| | | * |
| | | * @param storageAttachmentDTO å
³èè®°å½ä¿¡æ¯ |
| | | * @return åé¡µç»æ |
| | | */ |
| | | @GetMapping("/list") |
| | | @Operation(summary = "å页æ¥è¯¢éç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯") |
| | | public R list(StorageAttachmentDTO storageAttachmentDTO) { |
| | | return R.ok(storageAttachmentService.list(storageAttachmentDTO)); |
| | | } |
| | | |
| | | /** |
| | | * å é¤éç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯ |
| | | * |
| | | * @param ids æä»¶idå表 |
| | | * @return å é¤ç»æ |
| | | */ |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "å é¤éç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯") |
| | | public R batchDelete(@RequestBody List<Long> ids) { |
| | | return R.ok(storageAttachmentService.batchDeleteStorageAttachment(ids)); |
| | | } |
| | |
| | | * ä¿åéç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯ |
| | | */ |
| | | @PostMapping("/add") |
| | | @Operation(summary = "ä¿åéç¨æä»¶ä¸ä¼ çéä»¶ä¿¡æ¯") |
| | | public R add(@RequestBody StorageAttachmentDTO storageAttachmentDTO) { |
| | | storageAttachmentService.saveStorageAttachment(storageAttachmentDTO); |
| | | return R.ok(); |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.basic.pojo.StorageBlob; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Mapper |
| | | public interface StorageBlobMapper extends BaseMapper<StorageBlob> { |
| | | |
| | | java.util.List<StorageBlob> selectOrphanBlobsByIdRange(@Param("lastId") long lastId, @Param("limit") int limit); |
| | | |
| | | int deleteByIdList(@Param("ids") java.util.List<Long> ids); |
| | | |
| | | java.util.List<String> selectExistingUidFilenames(@Param("fileNames") java.util.List<String> fileNames); |
| | | } |
| | |
| | | @Excel(name = "è§æ ¼åå·") |
| | | private String model; |
| | | |
| | | @Excel(name = "产åç¼ç ") |
| | | @TableField("product_code") |
| | | private String productCode; |
| | | |
| | | /** |
| | | * åä½ |
| | | */ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.basic.task; |
| | | |
| | | import com.ruoyi.basic.mapper.StorageBlobMapper; |
| | | import com.ruoyi.basic.pojo.StorageBlob; |
| | | import com.ruoyi.common.config.FileProperties; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayDeque; |
| | | import java.util.ArrayList; |
| | | import java.util.Deque; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | /** |
| | | * æ¸
çæ ææä»¶å®æ¶ä»»å¡ã |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | @RequiredArgsConstructor |
| | | public class StorageBlobCleanupTask { |
| | | |
| | | private static final int DB_BATCH_SIZE = 500; |
| | | private static final int FILE_NAME_BATCH_SIZE = 1000; |
| | | |
| | | private final StorageBlobMapper storageBlobMapper; |
| | | private final FileProperties fileProperties; |
| | | |
| | | private final AtomicBoolean running = new AtomicBoolean(false); |
| | | |
| | | /** |
| | | * æ¯æ 1 å·åæ¨ 2 ç¹æ§è¡ä¸æ¬¡ï¼ |
| | | * 1. å é¤ storage_blob 䏿ªè¢« storage_attachment å
³èçè®°å½åå
¶æä»¶ |
| | | * 2. å é¤ç£çä¸ä¸åå¨äº storage_blob.uid_filename çæä»¶ |
| | | */ |
| | | @Scheduled(cron = "0 0 2 1 * ?") |
| | | public void cleanupUnusedStorageFiles() { |
| | | if (!running.compareAndSet(false, true)) { |
| | | log.warn("æä»¶æ¸
ç任塿£å¨æ§è¡ï¼æ¬æ¬¡è·³è¿"); |
| | | return; |
| | | } |
| | | |
| | | long start = System.currentTimeMillis(); |
| | | log.info("æä»¶æ¸
çä»»å¡å¼å§æ§è¡ï¼æ ¹ç®å½ï¼{}", fileProperties.getPath()); |
| | | try { |
| | | int removedBlobCount = cleanupOrphanStorageBlobs(); |
| | | int removedDiskFileCount = cleanupOrphanDiskFiles(); |
| | | long cost = System.currentTimeMillis() - start; |
| | | log.info("æä»¶æ¸
ç任塿§è¡å®æï¼å é¤å¤å¿ blob è®°å½ï¼{}ï¼å é¤ç£çæ ææä»¶ï¼{}ï¼èæ¶ï¼{} ms", |
| | | removedBlobCount, removedDiskFileCount, cost); |
| | | } catch (Exception e) { |
| | | log.error("æä»¶æ¸
ç任塿§è¡å¤±è´¥", e); |
| | | } finally { |
| | | running.set(false); |
| | | } |
| | | } |
| | | |
| | | private int cleanupOrphanStorageBlobs() { |
| | | long lastId = 0L; |
| | | int removedCount = 0; |
| | | |
| | | while (true) { |
| | | List<StorageBlob> orphanBlobs = storageBlobMapper.selectOrphanBlobsByIdRange(lastId, DB_BATCH_SIZE); |
| | | if (CollectionUtils.isEmpty(orphanBlobs)) { |
| | | break; |
| | | } |
| | | |
| | | List<Long> ids = new ArrayList<>(orphanBlobs.size()); |
| | | for (StorageBlob storageBlob : orphanBlobs) { |
| | | ids.add(storageBlob.getId()); |
| | | deleteBlobFiles(storageBlob); |
| | | } |
| | | storageBlobMapper.deleteByIdList(ids); |
| | | removedCount += ids.size(); |
| | | lastId = orphanBlobs.get(orphanBlobs.size() - 1).getId(); |
| | | |
| | | log.info("å·²å é¤ä¸æ¹å¤å¿ blobï¼batchSize={}ï¼lastId={}", ids.size(), lastId); |
| | | } |
| | | |
| | | return removedCount; |
| | | } |
| | | |
| | | private int cleanupOrphanDiskFiles() { |
| | | File rootDirectory = new File(fileProperties.getPath()); |
| | | if (!rootDirectory.exists() || !rootDirectory.isDirectory()) { |
| | | log.warn("æä»¶æ ¹ç®å½ä¸å卿䏿¯ç®å½ï¼è·³è¿ç£çæ¸
çï¼{}", fileProperties.getPath()); |
| | | return 0; |
| | | } |
| | | |
| | | int deletedCount = 0; |
| | | Deque<File> directories = new ArrayDeque<>(); |
| | | directories.push(rootDirectory); |
| | | |
| | | while (!directories.isEmpty()) { |
| | | File currentDirectory = directories.pop(); |
| | | File[] children = currentDirectory.listFiles(); |
| | | if (children == null || children.length == 0) { |
| | | continue; |
| | | } |
| | | |
| | | List<File> filesInDirectory = new ArrayList<>(); |
| | | for (File child : children) { |
| | | if (child.isDirectory()) { |
| | | directories.push(child); |
| | | } else if (child.isFile()) { |
| | | filesInDirectory.add(child); |
| | | } |
| | | } |
| | | |
| | | deletedCount += cleanupFilesInDirectory(filesInDirectory); |
| | | } |
| | | |
| | | return deletedCount; |
| | | } |
| | | |
| | | private int cleanupFilesInDirectory(List<File> filesInDirectory) { |
| | | if (CollectionUtils.isEmpty(filesInDirectory)) { |
| | | return 0; |
| | | } |
| | | |
| | | int deletedCount = 0; |
| | | for (int start = 0; start < filesInDirectory.size(); start += FILE_NAME_BATCH_SIZE) { |
| | | int end = Math.min(start + FILE_NAME_BATCH_SIZE, filesInDirectory.size()); |
| | | List<File> batchFiles = filesInDirectory.subList(start, end); |
| | | List<String> fileNames = new ArrayList<>(batchFiles.size()); |
| | | for (File file : batchFiles) { |
| | | fileNames.add(file.getName()); |
| | | } |
| | | |
| | | Set<String> existingFileNames = new HashSet<>(storageBlobMapper.selectExistingUidFilenames(fileNames)); |
| | | for (File file : batchFiles) { |
| | | if (!existingFileNames.contains(file.getName()) && safeDelete(file)) { |
| | | deletedCount++; |
| | | } |
| | | } |
| | | } |
| | | return deletedCount; |
| | | } |
| | | |
| | | private void deleteBlobFiles(StorageBlob storageBlob) { |
| | | File originalFile = resolveBlobFile(storageBlob); |
| | | safeDelete(originalFile); |
| | | |
| | | File compressedFile = resolveCompressedFile(originalFile); |
| | | safeDelete(compressedFile); |
| | | } |
| | | |
| | | private File resolveBlobFile(StorageBlob storageBlob) { |
| | | String basePath = fileProperties.getPath(); |
| | | if (!StringUtils.hasText(storageBlob.getPath())) { |
| | | return new File(basePath, storageBlob.getUidFilename()); |
| | | } |
| | | return new File(new File(basePath, storageBlob.getPath()), storageBlob.getUidFilename()); |
| | | } |
| | | |
| | | private File resolveCompressedFile(File originalFile) { |
| | | if (originalFile == null) { |
| | | return null; |
| | | } |
| | | File parent = originalFile.getParentFile(); |
| | | if (parent == null) { |
| | | return null; |
| | | } |
| | | return new File(parent, "thumb_" + originalFile.getName()); |
| | | } |
| | | |
| | | private boolean safeDelete(File file) { |
| | | if (file == null || !file.exists() || !file.isFile()) { |
| | | return false; |
| | | } |
| | | if (file.delete()) { |
| | | return true; |
| | | } |
| | | log.warn("å é¤æä»¶å¤±è´¥ï¼{}", file.getAbsolutePath()); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | PURCHASE_STOCK_IN("7", "éè´-å
¥åº"), |
| | | QUALITYINSPECT_STOCK_IN("6", "è´¨æ£-åæ ¼å
¥åº"), |
| | | DEFECTIVE_PASS("11", "ä¸åæ ¼-è®©æ¥æ¾è¡"), |
| | | RETURN_HE_IN("14", "éå®éè´§-åæ ¼å
¥åº"); |
| | | RETURN_HE_IN("14", "éå®éè´§-åæ ¼å
¥åº"), |
| | | PICK_RETURN_IN("20", "éå®éè´§-åæ ¼å
¥åº"); |
| | | |
| | | |
| | | private final String code; |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | |
| | | void export(HttpServletResponse response); |
| | | |
| | | boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException; |
| | | boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord; |
| | | import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerRecordService; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.sales.mapper.CommonFileMapper; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.IOException; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper; |
| | | private final MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper; |
| | | private final CommonFileMapper commonFileMapper; |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | @Override |
| | | public IPage<MeasuringInstrumentLedgerRecord> listPage(Page page, MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException { |
| | | public boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) { |
| | | MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord1 = measuringInstrumentLedgerRecordMapper.selectById(measuringInstrumentLedgerRecord.getId()); |
| | | if (measuringInstrumentLedgerRecord1 == null) { |
| | | return false; |
| | |
| | | measuringInstrumentLedgerMapper.updateById(measuringInstrumentLedger); |
| | | } |
| | | measuringInstrumentLedgerRecordMapper.updateById(measuringInstrumentLedgerRecord); |
| | | // è®°å½éä»¶ç»å® |
| | | migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), measuringInstrumentLedgerRecord.getTempFileIds(), FileNameType.MEASURINGRecord.getValue()); |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds,Integer fileType) throws IOException { |
| | | if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | fileRecord.setType(fileType); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // å é¤ä¸´æ¶æä»¶è®°å½ |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper; |
| | |
| | | import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord; |
| | | import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerService; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.sales.mapper.CommonFileMapper; |
| | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.IOException; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | private final MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper; |
| | | private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper; |
| | | private final TempFileMapper tempFileMapper; |
| | | private final CommonFileMapper commonFileMapper; |
| | | private final SysUserMapper sysUserMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | @Override |
| | | public IPage<MeasuringInstrumentLedger> listPage(Page page, MeasuringInstrumentLedger measuringInstrumentLedger) { |
| | |
| | | collect = measuringInstrumentLedgerRecords.stream().map(MeasuringInstrumentLedgerRecord::getId).collect(Collectors.toList()); |
| | | } |
| | | collect.add(item.getId()); |
| | | LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerFileWrapper.in(CommonFile::getCommonId, collect) |
| | | .in(CommonFile::getType,types); |
| | | List<CommonFile> commonFiles = commonFileMapper.selectList(salesLedgerFileWrapper); |
| | | item.setCommonFiles(commonFiles); |
| | | |
| | | }); |
| | | return measuringInstrumentLedgerIPage; |
| | | } |
| | |
| | | // if(!CollectionUtils.isEmpty(req.getTempFileIds())){ |
| | | // migrateTempFilesToFormal(measuringInstrumentLedger.getId(), req.getTempFileIds(), FileNameType.MEASURING.getValue()); |
| | | // } |
| | | // å°è´¦è®°å½ç»å®ä¸æ¬¡ |
| | | if(!CollectionUtils.isEmpty(req.getTempFileIds())){ |
| | | migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), req.getTempFileIds(), FileNameType.MEASURINGRecord.getValue()); |
| | | } |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | } |
| | | measuringInstrumentLedger.setUserName(sysUser.getUserName()); |
| | | measuringInstrumentLedgerMapper.insert(measuringInstrumentLedger); |
| | | if(!CollectionUtils.isEmpty(measuringInstrumentLedger.getTempFileIds())){ |
| | | migrateTempFilesToFormal(measuringInstrumentLedger.getId(), measuringInstrumentLedger.getTempFileIds(), FileNameType.MEASURING.getValue()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds,Integer fileType) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | fileRecord.setType(fileType); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // å é¤ä¸´æ¶æä»¶è®°å½ |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; |
| | | import com.ruoyi.stock.dto.StockInRecordDto; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.dto.StockUninventoryDto; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import com.ruoyi.stock.service.StockOutRecordService; |
| | | import com.ruoyi.stock.service.StockUninventoryService; |
| | | import com.ruoyi.stock.service.impl.StockInRecordServiceImpl; |
| | | import com.ruoyi.stock.service.impl.StockOutRecordServiceImpl; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | @Component |
| | | @RequiredArgsConstructor |
| | |
| | | |
| | | /** |
| | | * ä¸åæ ¼å
¥åº |
| | | * |
| | | * @param productModelId |
| | | * @param quantity |
| | | * @param recordType |
| | |
| | | |
| | | /** |
| | | * ä¸åæ ¼åºåº |
| | | * |
| | | * @param productModelId |
| | | * @param quantity |
| | | * @param recordType |
| | |
| | | |
| | | /** |
| | | * åæ ¼åºåº |
| | | * |
| | | * @param productModelId |
| | | * @param quantity |
| | | * @param recordType |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | public void deleteStockOutRecord(Long recordId, String recordType) { |
| | | StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>() |
| | | .lambda().eq(StockOutRecord::getRecordId, recordId) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.production.bean.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.production.pojo.ProductionAccount; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | @Data |
| | | @Schema(name = "ProductionAccountDto", description = "production account query dto") |
| | | public class ProductionAccountDto extends ProductionAccount { |
| | | |
| | | @Schema(description = "sales contract no") |
| | | private String salesContractNo; |
| | | |
| | | @Schema(description = "customer contract no") |
| | | private String customerContractNo; |
| | | |
| | | @Schema(description = "project name") |
| | | private String projectName; |
| | | |
| | | @Schema(description = "customer name") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "product category") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "specification model") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "scheduling user id") |
| | | private Long schedulingUserId; |
| | | |
| | | @Schema(description = "scheduling user name") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "process") |
| | | private String process; |
| | | |
| | | @Schema(description = "date type(day/month)") |
| | | private String dateType; |
| | | |
| | | @Schema(description = "day query date") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDate; |
| | | |
| | | @Schema(description = "date range") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate[] dateRange; |
| | | |
| | | @Schema(description = "start date") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDateStart; |
| | | |
| | | @Schema(description = "end date") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDateEnd; |
| | | } |
| | |
| | | package com.ruoyi.production.bean.dto; |
| | | |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class ProductionOperationTaskDto extends ProductionOperationTask { |
| | | |
| | | @Schema(description = "å·¥åºåç§°") |
| | | private String processName; |
| | | |
| | | @Schema(description = "ç产订åå·") |
| | | private String productOrderNpsNo; |
| | | |
| | | @Schema(description = "产ååç§°") |
| | | private String productName; |
| | | |
| | | @Schema(description = "è§æ ¼åå·") |
| | | private String model; |
| | | |
| | | @Schema(description = "åä½") |
| | | private String unit; |
| | | |
| | | @Schema(description = "æ¥åºæ°é") |
| | | private BigDecimal scrapQty; |
| | | |
| | | @Schema(description = "宿è¿åº¦") |
| | | private BigDecimal completionStatus; |
| | | } |
| | |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | @Schema(name = "ProductionProductMainDto", description = "ç产æ¥å·¥æ¥è¯¢å¯¹è±¡") |
| | | @Schema(name = "ProductionProductMainDto", description = "production report query dto") |
| | | public class ProductionProductMainDto extends ProductionProductMain { |
| | | |
| | | @Schema(description = "产åå·¥èºè·¯çº¿æç»ID") |
| | | @Schema(description = "product process route item id") |
| | | private Long productProcessRouteItemId; |
| | | |
| | | @Schema(description = "ç产æ¥å·¥è¡¨id") |
| | | @Schema(description = "production report id") |
| | | private Long productMainId; |
| | | |
| | | @Schema(description = "ç§æ·ID") |
| | | @Schema(description = "tenant id") |
| | | private Long tenantId; |
| | | |
| | | @Schema(description = "å·¥åç¼å·") |
| | | @Schema(description = "work order no") |
| | | private String workOrderNo; |
| | | |
| | | @Schema(description = "å·¥åç¶æ") |
| | | @Schema(description = "work order status") |
| | | private String workOrderStatus; |
| | | |
| | | @Schema(description = "æµç§°") |
| | | @Schema(description = "nick name") |
| | | private String nickName; |
| | | |
| | | @Schema(description = "æ°é") |
| | | @Schema(description = "quantity") |
| | | private BigDecimal quantity; |
| | | |
| | | @Schema(description = "æ¥åºæ°é") |
| | | @Schema(description = "scrap quantity") |
| | | private BigDecimal scrapQty; |
| | | |
| | | @Schema(description = "产ååç§°") |
| | | @Schema(description = "product name") |
| | | private String productName; |
| | | |
| | | @Schema(description = "产ååå·åç§°") |
| | | @Schema(description = "product model name") |
| | | private String productModelName; |
| | | |
| | | @Schema(description = "åä½") |
| | | @Schema(description = "unit") |
| | | private String unit; |
| | | |
| | | @Schema(description = "éå®ååç¼å·") |
| | | @Schema(description = "sales contract no") |
| | | private String salesContractNo; |
| | | |
| | | @Schema(description = "æäº§æ¥æ") |
| | | @Schema(description = "scheduling date") |
| | | private LocalDate schedulingDate; |
| | | |
| | | @Schema(description = "æäº§äººååç§°") |
| | | @Schema(description = "scheduling user name") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "客æ·åç§°") |
| | | @Schema(description = "customer name") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "å·¥åº") |
| | | @Schema(description = "process") |
| | | private String process; |
| | | |
| | | @Schema(description = "å·¥åºåæ°å表") |
| | | @Schema(description = "salary quota") |
| | | private BigDecimal workHours; |
| | | |
| | | @Schema(description = "wages") |
| | | private BigDecimal wages; |
| | | |
| | | @Schema(description = "operation param list") |
| | | private List<ProductionOrderRoutingOperationParam> productionOperationParamList; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.production.bean.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | |
| | | @Data |
| | | @Schema(name = "ProductionAccountVo", description = "production account page result") |
| | | public class ProductionAccountVo { |
| | | |
| | | @Schema(description = "customer contract no") |
| | | private String customerContractNo; |
| | | |
| | | @Schema(description = "project name") |
| | | private String projectName; |
| | | |
| | | @Schema(description = "customer name") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "product category") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "specification model") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "unit") |
| | | private String unit; |
| | | |
| | | @Schema(description = "scheduling user id") |
| | | private Long schedulingUserId; |
| | | |
| | | @Schema(description = "scheduling user name") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "wages") |
| | | private BigDecimal wages; |
| | | |
| | | @Schema(description = "finished quantity") |
| | | private BigDecimal finishedNum; |
| | | |
| | | @Schema(description = "salary quota") |
| | | private BigDecimal workHours; |
| | | |
| | | @Schema(description = "output rate") |
| | | private String outputRate; |
| | | |
| | | @Schema(description = "process") |
| | | private String process; |
| | | |
| | | @Schema(description = "scheduling date") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate schedulingDate; |
| | | |
| | | @Schema(description = "scheduling month(yyyy-MM)") |
| | | private String schedulingMonth; |
| | | } |
| | |
| | | |
| | | @Schema(description = "宿è¿åº¦") |
| | | private BigDecimal completionStatus; |
| | | |
| | | @Schema(description = "æ¥å·¥äººååç§°ï¼å¤ä¸ªä½¿ç¨éå·åé") |
| | | private String userNames; |
| | | |
| | | @Schema(description = "æ¯å¦ç»æï¼") |
| | | private Boolean endOrder; |
| | | } |
| | |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | |
| | | |
| | | @Schema(description = "bomç¼å·") |
| | | private String bomNo; |
| | | |
| | | @Schema(description = "宿è¿åº¦") |
| | | private BigDecimal completionStatus; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.production.bean.vo; |
| | | |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam; |
| | | import com.ruoyi.production.pojo.ProductionProductMain; |
| | | import com.ruoyi.production.pojo.ProductionProductOutput; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityInspectFile; |
| | | import com.ruoyi.quality.pojo.QualityInspectParam; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @Schema(name = "ProductionOrderWorkOrderDetailVo", description = "Production order work order/report/inspect detail") |
| | | public class ProductionOrderWorkOrderDetailVo { |
| | | |
| | | @Schema(description = "Production order info") |
| | | private ProductionOrderVo productionOrder; |
| | | |
| | | @Schema(description = "Work order list") |
| | | private List<WorkOrderDetail> workOrderList; |
| | | |
| | | @Data |
| | | @Schema(name = "WorkOrderDetail", description = "Work order detail") |
| | | public static class WorkOrderDetail { |
| | | |
| | | @Schema(description = "Work order info") |
| | | private ProductionOperationTask workOrder; |
| | | |
| | | @Schema(description = "Report list under current work order") |
| | | private List<ReportDetail> reportList; |
| | | } |
| | | |
| | | @Data |
| | | @Schema(name = "ReportDetail", description = "Production report detail") |
| | | public static class ReportDetail { |
| | | |
| | | @Schema(description = "Report main info") |
| | | private ProductionProductMain reportMain; |
| | | |
| | | @Schema(description = "Report output list") |
| | | private List<ProductionProductOutput> reportOutputList; |
| | | |
| | | @Schema(description = "Report process param list") |
| | | private List<ProductionOrderRoutingOperationParam> reportParamList; |
| | | |
| | | @Schema(description = "Inspect list under current report") |
| | | private List<InspectDetail> inspectList; |
| | | } |
| | | |
| | | @Data |
| | | @Schema(name = "InspectDetail", description = "Quality inspect detail") |
| | | public static class InspectDetail { |
| | | |
| | | @Schema(description = "Inspect main info") |
| | | private QualityInspect inspect; |
| | | |
| | | @Schema(description = "Inspect param list") |
| | | private List<QualityInspectParam> inspectParamList; |
| | | |
| | | @Schema(description = "Inspect attachment list") |
| | | private List<QualityInspectFile> inspectFileList; |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.production.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import com.ruoyi.production.bean.dto.ProductionAccountDto; |
| | | import com.ruoyi.production.bean.dto.ProductionProductMainDto; |
| | | import com.ruoyi.production.bean.vo.ProductionAccountVo; |
| | | import com.ruoyi.production.service.ProductionAccountService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | |
| | | * <p> |
| | | * çäº§æ ¸ç®è¡¨ å端æ§å¶å¨ |
| | | * </p> |
| | | * |
| | | * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå
¬å¸ |
| | | * @since 2026-04-21 03:55:52 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/productionAccount") |
| | | @RequiredArgsConstructor |
| | | @Tag(name = "çäº§æ ¸ç®") |
| | | public class ProductionAccountController { |
| | | |
| | | private final ProductionAccountService productionAccountService; |
| | | |
| | | @GetMapping("/listPage") |
| | | @Operation(summary = "çäº§æ ¸ç®å页æ¥è¯¢") |
| | | public R<IPage<ProductionAccountVo>> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) { |
| | | return R.ok(productionAccountService.listPage(page, dto)); |
| | | } |
| | | |
| | | @GetMapping("/listProductionDetails") |
| | | @Operation(summary ="æ¥è¯¢å·¥äººç产工èµä¿¡æ¯") |
| | | public R<IPage<ProductionProductMainDto>> listProductionDetails(ProductionAccountDto productionAccountDto, Page page) { |
| | | return R.ok(productionAccountService.listProductionDetails(productionAccountDto,page)); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.service.ProductionOperationTaskService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.DeleteMapping; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.PutMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | return R.ok(productionOperationTaskService.updateProductWorkOrder(dto)); |
| | | } |
| | | |
| | | @Operation(summary = "ææ´¾æ¥å·¥äºº") |
| | | @PostMapping("/assign") |
| | | public R<Boolean> assign(@RequestBody ProductionOperationTaskDto dto) { |
| | | return R.ok(productionOperationTaskService.assign(dto)); |
| | | } |
| | | |
| | | /** |
| | | * å·¥åæµè½¬å¡ä¸è½½ |
| | | * @param response |
| | | * @param dto |
| | | */ |
| | | @PostMapping("/down") |
| | | public void down(HttpServletResponse response, @RequestBody ProductionOperationTaskDto dto) { |
| | | productionOperationTaskService.down(response, dto); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.ruoyi.production.bean.vo.ProductionOrderPickVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderVo; |
| | | import com.ruoyi.production.bean.vo.ProductionPlanVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.service.ProductionOrderService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | public R<List<ProductionOrderPickVo>> pick(@PathVariable Long productionOrderId) { |
| | | return R.ok(productionOrderService.pick(productionOrderId)); |
| | | } |
| | | |
| | | @GetMapping("/workOrder/detail/{productionOrderId}") |
| | | @Operation(summary = "Query work orders/reports/inspects by production order id") |
| | | public R<ProductionOrderWorkOrderDetailVo> getWorkOrderReportInspectDetail(@PathVariable Long productionOrderId) { |
| | | return R.ok(productionOrderService.getWorkOrderReportInspectDetail(productionOrderId)); |
| | | } |
| | | |
| | | @Operation(summary = "æ´æ°è®¢åç¶æ") |
| | | @PostMapping("/updateOrder") |
| | | public R updateOrder(@RequestBody ProductionOrderDto productionOrderDto) { |
| | | return R.ok(productionOrderService.updateOrder(productionOrderDto)); |
| | | } |
| | | } |
| | |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | |
| | | * @return |
| | | */ |
| | | @PostMapping("/addProductMain") |
| | | @PreAuthorize("@ss.hasPermi('productionProductMain:add')") |
| | | public R addProductMain(@RequestBody ProductionProductMainDto productionProductMainDto) { |
| | | return R.ok(productionProductMainService.addProductMain(productionProductMainDto)); |
| | | } |
| | |
| | | package com.ruoyi.production.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.production.bean.dto.ProductionAccountDto; |
| | | import com.ruoyi.production.bean.dto.UserAccountDto; |
| | | import com.ruoyi.production.bean.vo.ProductionAccountVo; |
| | | import com.ruoyi.production.pojo.ProductionAccount; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | |
| | | */ |
| | | @Mapper |
| | | public interface ProductionAccountMapper extends BaseMapper<ProductionAccount> { |
| | | IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, @Param("c") ProductionAccountDto dto); |
| | | |
| | | UserAccountDto selectUserAccount(@Param("userId") Long userId, @Param("date") String date); |
| | | |
| | | List<Map<String, Object>> selectDailyWagesStats(@Param("startDate") String startDate, @Param("endDate") String endDate); |
| | |
| | | @Param("userId") Long userId, |
| | | @Param("processIds") List<Long> processIds); |
| | | |
| | | ProductionOperationTaskDto getProductWorkOrderFlowCard(@Param("id") Long id); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.production.bean.dto.ProductionAccountDto; |
| | | import com.ruoyi.production.bean.dto.ProductionProductMainDto; |
| | | import com.ruoyi.production.bean.dto.SalesLedgerProductionAccountingDto; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionProductMain; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | |
| | | */ |
| | | ProductionOrder getOrderByMainId(@Param("productMainId") Long productMainId); |
| | | |
| | | IPage<ProductionProductMainDto> listProductionDetails(@Param("ew") SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page); |
| | | IPage<ProductionProductMainDto> listProductionDetails(@Param("c") ProductionAccountDto productionAccountDto, Page page); |
| | | |
| | | ArrayList<Long> listMain(List<Long> idList); |
| | | } |
| | |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate planCompleteTime; |
| | | |
| | | @Schema(description = "ç¶æï¼1.å¾
å¼å§ 2.è¿è¡ä¸ 3.已宿 4.已忶ï¼") |
| | | @Schema(description = "ç¶æï¼1.å¾
å¼å§ 2.è¿è¡ä¸ 3.已宿 4.已忶 5.å·²ç»æï¼") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "æ¯å¦ç»æï¼") |
| | | @TableField("is_end_order") |
| | | private Boolean endOrder; |
| | | } |
| | |
| | | |
| | | @Schema(description = "ç产订åå·¥èºè·¯çº¿å·¥åºID") |
| | | private Long productionOrderRoutingOperationId; |
| | | |
| | | @Schema(description = "ç产æ¥å·¥è¡¨ID") |
| | | private Long productionProductMainId; |
| | | } |
| | |
| | | @Schema(description = "产åid") |
| | | private Long productModelId; |
| | | |
| | | @Schema(description = "æ¥å·¥æ°é(æ»æ°é)") |
| | | @Schema(description = "åæ ¼æ°é") |
| | | private BigDecimal quantity; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | |
| | | package com.ruoyi.production.service; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.production.bean.dto.ProductionAccountDto; |
| | | import com.ruoyi.production.bean.dto.ProductionProductMainDto; |
| | | import com.ruoyi.production.bean.vo.ProductionAccountVo; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.production.pojo.ProductionAccount; |
| | | |
| | |
| | | * @since 2026-04-21 03:55:52 |
| | | */ |
| | | public interface ProductionAccountService extends IService<ProductionAccount> { |
| | | IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto); |
| | | |
| | | IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto productionAccountDto, Page page); |
| | | } |
| | |
| | | import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; |
| | | import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | boolean removeProductionOperationTask(List<Long> ids); |
| | | |
| | | int updateProductWorkOrder(ProductionOperationTaskDto dto); |
| | | |
| | | boolean assign(ProductionOperationTaskDto dto); |
| | | |
| | | void down(HttpServletResponse response, ProductionOperationTaskDto dto); |
| | | } |
| | |
| | | import com.ruoyi.production.bean.vo.ProductionOrderPickVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderVo; |
| | | import com.ruoyi.production.bean.vo.ProductionPlanVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | |
| | | import java.util.List; |
| | |
| | | List<ProductionPlanVo> getSource(Long id); |
| | | |
| | | List<ProductionOrderPickVo> pick(Long productionOrderId); |
| | | |
| | | ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(Long productionOrderId); |
| | | |
| | | int updateOrder(ProductionOrderDto productionOrderDto); |
| | | } |
| | |
| | | package com.ruoyi.production.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.production.bean.dto.ProductionAccountDto; |
| | | import com.ruoyi.production.bean.dto.ProductionProductMainDto; |
| | | import com.ruoyi.production.bean.vo.ProductionAccountVo; |
| | | import com.ruoyi.production.mapper.ProductionAccountMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | import com.ruoyi.production.pojo.ProductionAccount; |
| | | import com.ruoyi.production.service.ProductionAccountService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * çäº§æ ¸ç®è¡¨ æå¡å®ç°ç±» |
| | | * </p> |
| | | * |
| | | * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå
¬å¸ |
| | | * @since 2026-04-21 03:55:52 |
| | | */ |
| | | import java.time.LocalDate; |
| | | |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ProductionAccountServiceImpl extends ServiceImpl<ProductionAccountMapper, ProductionAccount> implements ProductionAccountService { |
| | | |
| | | |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | |
| | | @Override |
| | | public IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) { |
| | | ProductionAccountDto queryDto = normalizeDateQuery(dto); |
| | | return baseMapper.listPage(page, queryDto); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto dto, Page page) { |
| | | return productionProductMainMapper.listProductionDetails(normalizeDateQuery(dto), page); |
| | | } |
| | | |
| | | private ProductionAccountDto normalizeDateQuery(ProductionAccountDto dto) { |
| | | if (dto == null) { |
| | | return new ProductionAccountDto(); |
| | | } |
| | | LocalDate[] dateRange = dto.getDateRange(); |
| | | if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null) |
| | | && dateRange != null |
| | | && dateRange.length > 0) { |
| | | if (dto.getEntryDateStart() == null) { |
| | | dto.setEntryDateStart(dateRange[0]); |
| | | } |
| | | if (dto.getEntryDateEnd() == null) { |
| | | dto.setEntryDateEnd(dateRange.length > 1 ? dateRange[1] : dateRange[0]); |
| | | } |
| | | } |
| | | |
| | | String dateType = dto.getDateType(); |
| | | if ("day".equalsIgnoreCase(dateType)) { |
| | | if (dto.getEntryDate() == null && dateRange != null && dateRange.length > 0) { |
| | | dto.setEntryDate(dateRange[0]); |
| | | } |
| | | if (dto.getEntryDate() == null) { |
| | | dto.setEntryDate(dto.getEntryDateStart()); |
| | | } |
| | | dto.setEntryDateStart(null); |
| | | dto.setEntryDateEnd(null); |
| | | } else if ("month".equalsIgnoreCase(dateType)) { |
| | | if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null) && dto.getEntryDate() != null) { |
| | | LocalDate monthDate = dto.getEntryDate(); |
| | | dto.setEntryDateStart(monthDate.withDayOfMonth(1)); |
| | | dto.setEntryDateEnd(monthDate.withDayOfMonth(monthDate.lengthOfMonth())); |
| | | } |
| | | dto.setEntryDate(null); |
| | | } |
| | | return dto; |
| | | } |
| | | |
| | | } |
| | |
| | | package com.ruoyi.production.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.data.PictureRenderData; |
| | | import com.deepoove.poi.data.PictureType; |
| | | import com.deepoove.poi.data.Pictures; |
| | | import com.ruoyi.basic.dto.StorageAttachmentDTO; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.config.FileProperties; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.MatrixToImageWriter; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; |
| | | import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; |
| | | import com.ruoyi.production.mapper.ProductionOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionOperationTaskMapper; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.service.ProductionOperationTaskService; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask> implements ProductionOperationTaskService { |
| | | |
| | | private final SysUserMapper sysUserMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | |
| | | private final FileUtil fileUtil; |
| | | |
| | | private final FileProperties fileProperties; |
| | | |
| | | @Value("${file.temp-dir}") |
| | | private String tempDir; |
| | | |
| | | @Override |
| | | public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { |
| | | Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); |
| | | return baseMapper.pageProductionOperationTask(voPage, dto); |
| | | IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto); |
| | | fillUserNames(result.getRecords()); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) { |
| | | return BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class); |
| | | List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class); |
| | | fillUserNames(result); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public ProductionOperationTaskVo getProductionOperationTaskInfo(Long id) { |
| | | ProductionOperationTask item = this.getById(id); |
| | | return item == null ? null : BeanUtil.copyProperties(item, ProductionOperationTaskVo.class); |
| | | if (item == null) { |
| | | return null; |
| | | } |
| | | ProductionOperationTaskVo vo = BeanUtil.copyProperties(item, ProductionOperationTaskVo.class); |
| | | if (item.getProductionOrderId() != null) { |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(item.getProductionOrderId()); |
| | | if (productionOrder != null) { |
| | | vo.setEndOrder(productionOrder.getEndOrder()); |
| | | } |
| | | } |
| | | fillUserNames(Collections.singletonList(vo)); |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Override |
| | | public boolean removeProductionOperationTask(List<Long> ids) { |
| | | return ids != null && !ids.isEmpty() && this.removeByIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public int updateProductWorkOrder(ProductionOperationTaskDto dto) { |
| | | return baseMapper.updateById(dto); |
| | | } |
| | | |
| | | @Override |
| | | public boolean assign(ProductionOperationTaskDto dto) { |
| | | if (dto == null || dto.getId() == null) { |
| | | throw new ServiceException("å·¥åIDä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | ProductionOperationTask update = new ProductionOperationTask(); |
| | | update.setId(dto.getId()); |
| | | update.setUserIds(dto.getUserIds()); |
| | | int rows = baseMapper.updateById(update); |
| | | if (rows <= 0) { |
| | | throw new ServiceException("å·¥åä¸å卿已å é¤"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private LambdaQueryWrapper<ProductionOperationTask> buildQueryWrapper(ProductionOperationTaskDto dto) { |
| | |
| | | .orderByDesc(ProductionOperationTask::getId); |
| | | } |
| | | |
| | | private void fillUserNames(List<ProductionOperationTaskVo> voList) { |
| | | if (voList == null || voList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> userIdSet = new LinkedHashSet<>(); |
| | | for (ProductionOperationTaskVo vo : voList) { |
| | | if (vo == null) { |
| | | continue; |
| | | } |
| | | userIdSet.addAll(parseUserIdList(vo.getUserIds(), false)); |
| | | } |
| | | if (userIdSet.isEmpty()) { |
| | | return; |
| | | } |
| | | List<SysUser> userList = sysUserMapper.selectUsersByIds(new ArrayList<>(userIdSet)); |
| | | if (userList == null || userList.isEmpty()) { |
| | | return; |
| | | } |
| | | Map<Long, String> userNameById = userList.stream() |
| | | .filter(item -> item.getUserId() != null) |
| | | .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (left, right) -> left)); |
| | | |
| | | for (ProductionOperationTaskVo vo : voList) { |
| | | if (vo == null) { |
| | | continue; |
| | | } |
| | | List<Long> userIds = parseUserIdList(vo.getUserIds(), false); |
| | | if (userIds.isEmpty()) { |
| | | vo.setUserNames(null); |
| | | continue; |
| | | } |
| | | String userNames = userIds.stream() |
| | | .map(userNameById::get) |
| | | .filter(StringUtils::isNotBlank) |
| | | .collect(Collectors.joining(",")); |
| | | vo.setUserNames(userNames); |
| | | } |
| | | } |
| | | |
| | | private List<Long> parseUserIdList(String userIds, boolean strict) { |
| | | if (StringUtils.isBlank(userIds)) { |
| | | if (strict) { |
| | | throw new ServiceException("userIdsæ ¼å¼ä¸æ£ç¡®ï¼å¿
须为JSONæ°åæ°ç»"); |
| | | } |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | String text = userIds.trim(); |
| | | try { |
| | | List<Long> parsed = JSON.parseArray(text, Long.class); |
| | | LinkedHashSet<Long> idSet = parsed == null ? new LinkedHashSet<>() : parsed.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (strict && idSet.isEmpty()) { |
| | | throw new ServiceException("userIdsæ ¼å¼ä¸æ£ç¡®ï¼å¿
须为JSONæ°åæ°ç»"); |
| | | } |
| | | return new ArrayList<>(idSet); |
| | | } catch (Exception e) { |
| | | if (strict) { |
| | | throw new ServiceException("userIdsæ ¼å¼ä¸æ£ç¡®ï¼å¿
须为JSONæ°åæ°ç»"); |
| | | } |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public int updateProductWorkOrder(ProductionOperationTaskDto dto) { |
| | | return baseMapper.updateById(dto); |
| | | public void down(HttpServletResponse response, ProductionOperationTaskDto dto) { |
| | | if (dto == null || dto.getId() == null) { |
| | | throw new ServiceException("å·¥åIDä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | ProductionOperationTaskDto taskDto = baseMapper.getProductWorkOrderFlowCard(dto.getId()); |
| | | if (taskDto == null) { |
| | | throw new ServiceException("å·¥åä¸åå¨ï¼ID=" + dto.getId()); |
| | | } |
| | | String codePath; |
| | | try { |
| | | codePath = new MatrixToImageWriter().code(taskDto.getId().toString(), tempDir); |
| | | } catch (Exception e) { |
| | | throw new ServiceException("çæäºç»´ç 失败"); |
| | | } |
| | | |
| | | List<Map<String, Object>> images = buildTaskAttachmentImages(taskDto.getId()); |
| | | Map<String, Object> renderData = new HashMap<>(); |
| | | renderData.put("process", taskDto.getProcessName()); |
| | | renderData.put("workOrderNo", taskDto.getWorkOrderNo()); |
| | | renderData.put("productOrderNpsNo", taskDto.getProductOrderNpsNo()); |
| | | renderData.put("productName", taskDto.getProductName()); |
| | | renderData.put("planQuantity", taskDto.getPlanQuantity()); |
| | | renderData.put("model", taskDto.getModel()); |
| | | renderData.put("completeQuantity", taskDto.getCompleteQuantity()); |
| | | renderData.put("scrapQty", taskDto.getScrapQty()); |
| | | renderData.put("planStartTime", taskDto.getPlanStartTime()); |
| | | renderData.put("planEndTime", taskDto.getPlanEndTime()); |
| | | renderData.put("actualStartTime", taskDto.getActualStartTime()); |
| | | renderData.put("actualEndTime", taskDto.getActualEndTime()); |
| | | renderData.put("twoCode", Pictures.ofLocal(codePath).create()); |
| | | renderData.put("images", images.isEmpty() ? null : images); |
| | | |
| | | try (InputStream inputStream = this.getClass().getResourceAsStream("/static/work-order-template.docx")) { |
| | | if (inputStream == null) { |
| | | throw new ServiceException("æµè½¬å¡æ¨¡æ¿ä¸åå¨"); |
| | | } |
| | | XWPFTemplate template = XWPFTemplate.compile(inputStream).render(renderData); |
| | | response.setContentType("application/msword"); |
| | | String fileName = URLEncoder.encode("æµè½¬å¡", "UTF-8"); |
| | | response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); |
| | | response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx"); |
| | | try (OutputStream os = response.getOutputStream()) { |
| | | template.write(os); |
| | | os.flush(); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("导åºå¤±è´¥"); |
| | | } |
| | | } |
| | | |
| | | private List<Map<String, Object>> buildTaskAttachmentImages(Long taskId) { |
| | | List<Map<String, Object>> images = new ArrayList<>(); |
| | | StorageAttachmentDTO storageAttachmentDTO = new StorageAttachmentDTO(); |
| | | storageAttachmentDTO.setRecordType(RecordTypeEnum.PRODUCTION_OPERATION_TASK.getType()); |
| | | storageAttachmentDTO.setRecordId(taskId); |
| | | List<StorageBlobVO> taskWorkOrderFiles = |
| | | fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(storageAttachmentDTO); |
| | | if (CollectionUtils.isEmpty(taskWorkOrderFiles)) { |
| | | return images; |
| | | } |
| | | for (StorageBlobVO blobVO : taskWorkOrderFiles) { |
| | | if (blobVO == null) { |
| | | continue; |
| | | } |
| | | PictureType pictureType = resolvePictureType(blobVO); |
| | | if (pictureType == null) { |
| | | continue; |
| | | } |
| | | File imageFile = resolveImageFile(blobVO); |
| | | if (imageFile == null || !imageFile.exists() || !imageFile.isFile()) { |
| | | continue; |
| | | } |
| | | try (InputStream imageInputStream = new FileInputStream(imageFile)) { |
| | | Map<String, Object> image = new HashMap<>(); |
| | | PictureRenderData pictureRenderData = Pictures.ofStream(imageInputStream, pictureType) |
| | | .sizeInCm(17, 20) |
| | | .create(); |
| | | image.put("url", pictureRenderData); |
| | | images.add(image); |
| | | } catch (Exception ignored) { |
| | | // å个éä»¶è§£æå¤±è´¥æ¶è·³è¿ï¼é¿å
å½±åæ´ä¸ªæµè½¬å¡å¯¼åº |
| | | } |
| | | } |
| | | return images; |
| | | } |
| | | |
| | | private File resolveImageFile(StorageBlobVO blobVO) { |
| | | if (blobVO == null || StringUtils.isBlank(blobVO.getUidFilename())) { |
| | | return null; |
| | | } |
| | | if (StringUtils.isBlank(blobVO.getPath())) { |
| | | return new File(fileProperties.getPath(), blobVO.getUidFilename()); |
| | | } |
| | | return new File(new File(fileProperties.getPath(), blobVO.getPath()), blobVO.getUidFilename()); |
| | | } |
| | | |
| | | private PictureType resolvePictureType(StorageBlobVO blobVO) { |
| | | if (blobVO == null) { |
| | | return null; |
| | | } |
| | | PictureType type = parsePictureTypeByFileName(blobVO.getOriginalFilename()); |
| | | if (type != null) { |
| | | return type; |
| | | } |
| | | type = parsePictureTypeByFileName(blobVO.getUidFilename()); |
| | | if (type != null) { |
| | | return type; |
| | | } |
| | | return parsePictureTypeByContentType(blobVO.getContentType()); |
| | | } |
| | | |
| | | private PictureType parsePictureTypeByFileName(String fileName) { |
| | | if (StringUtils.isBlank(fileName) || !fileName.contains(".")) { |
| | | return null; |
| | | } |
| | | try { |
| | | return PictureType.suggestFileType(fileName); |
| | | } catch (Exception ex) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private PictureType parsePictureTypeByContentType(String contentType) { |
| | | if (StringUtils.isBlank(contentType)) { |
| | | return null; |
| | | } |
| | | String normalized = contentType.trim().toLowerCase(Locale.ROOT); |
| | | switch (normalized) { |
| | | case "image/jpeg": |
| | | case "image/jpg": |
| | | case "image/pjpeg": |
| | | return PictureType.JPEG; |
| | | case "image/png": |
| | | return PictureType.PNG; |
| | | case "image/gif": |
| | | return PictureType.GIF; |
| | | case "image/bmp": |
| | | case "image/x-ms-bmp": |
| | | return PictureType.BMP; |
| | | case "image/tiff": |
| | | case "image/tif": |
| | | return PictureType.TIFF; |
| | | case "image/svg+xml": |
| | | return PictureType.SVG; |
| | | default: |
| | | return null; |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.production.bean.dto.ProductionOrderPickDto; |
| | |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInventory; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | List<String> batchNoList = resolveBatchNoList(resolvedDto); |
| | | String inventoryBatchNo = pickInventoryBatchNo(batchNoList); |
| | | String storedBatchNo = formatBatchNoStorage(batchNoList); |
| | | subtractInventory(resolvedDto.getProductModelId(), inventoryBatchNo, resolvedDto.getPickQuantity(), rowNo); |
| | | subtractInventory(resolvedDto.getProductModelId(), storedBatchNo, resolvedDto.getPickQuantity(), rowNo); |
| | | |
| | | ProductionOrderPick orderPick = new ProductionOrderPick(); |
| | | orderPick.setProductionOrderId(resolvedDto.getProductionOrderId()); |
| | |
| | | List<String> batchNoList = resolveBatchNoList(dto); |
| | | String inventoryBatchNo = pickInventoryBatchNo(batchNoList); |
| | | String storedBatchNo = formatBatchNoStorage(batchNoList); |
| | | subtractInventory(dto.getProductModelId(), inventoryBatchNo, dto.getPickQuantity(), rowNo); |
| | | subtractInventory(dto.getProductModelId(), storedBatchNo, dto.getPickQuantity(), rowNo); |
| | | |
| | | ProductionOrderPick orderPick = new ProductionOrderPick(); |
| | | orderPick.setProductionOrderId(dto.getProductionOrderId()); |
| | |
| | | List<String> batchNoList = resolveBatchNoList(dto); |
| | | String inventoryBatchNo = batchNoList.isEmpty() |
| | | ? resolveInventoryBatchNoFromStored(oldPick.getBatchNo()) |
| | | : pickInventoryBatchNo(batchNoList); |
| | | : formatBatchNoStorage(batchNoList); |
| | | BigDecimal feedingQuantity = dto.getFeedingQuantity(); |
| | | |
| | | subtractInventory(productModelId, inventoryBatchNo, feedingQuantity, rowNo); |
| | |
| | | if (sameStockKey) { |
| | | BigDecimal delta = newQuantity.subtract(oldQuantity); |
| | | if (delta.compareTo(BigDecimal.ZERO) > 0) { |
| | | subtractInventory(newProductModelId, newBatchNo, delta, rowNo); |
| | | subtractInventory(newProductModelId, newStoredBatchNo, delta, rowNo); |
| | | } else if (delta.compareTo(BigDecimal.ZERO) < 0) { |
| | | addInventory(oldProductModelId, oldBatchNo, delta.abs()); |
| | | } |
| | | } else { |
| | | addInventory(oldProductModelId, oldBatchNo, oldQuantity); |
| | | subtractInventory(newProductModelId, newBatchNo, newQuantity, rowNo); |
| | | subtractInventory(newProductModelId, newStoredBatchNo, newQuantity, rowNo); |
| | | } |
| | | |
| | | oldPick.setProductModelId(newProductModelId); |
| | |
| | | } |
| | | |
| | | private void subtractInventory(Long productModelId, String batchNo, BigDecimal quantity, int rowNo) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo)); |
| | | if (stockInventory == null) { |
| | | throw new ServiceException("第" + rowNo + "æ¡é¢æå¯¹åºåºåä¸åå¨"); |
| | | BigDecimal deductQuantity = defaultDecimal(quantity); |
| | | if (deductQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | BigDecimal availableQuantity = defaultDecimal(stockInventory.getQualitity()) |
| | | |
| | | List<String> batchNoList = parseBatchNoValue(batchNo); |
| | | if (batchNoList.isEmpty()) { |
| | | batchNoList = Collections.singletonList(null); |
| | | } |
| | | |
| | | Map<String, BigDecimal> availableQuantityMap = new LinkedHashMap<>(); |
| | | BigDecimal totalAvailableQuantity = BigDecimal.ZERO; |
| | | for (String currentBatchNo : batchNoList) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, currentBatchNo)); |
| | | BigDecimal availableQuantity = BigDecimal.ZERO; |
| | | if (stockInventory != null) { |
| | | availableQuantity = defaultDecimal(stockInventory.getQualitity()) |
| | | .subtract(defaultDecimal(stockInventory.getLockedQuantity())); |
| | | if (quantity.compareTo(availableQuantity) > 0) { |
| | | throw new ServiceException("第" + rowNo + "æ¡é¢æå¯ç¨åºåä¸è¶³"); |
| | | if (availableQuantity.compareTo(BigDecimal.ZERO) < 0) { |
| | | availableQuantity = BigDecimal.ZERO; |
| | | } |
| | | } |
| | | availableQuantityMap.put(currentBatchNo, availableQuantity); |
| | | totalAvailableQuantity = totalAvailableQuantity.add(availableQuantity); |
| | | } |
| | | |
| | | if (deductQuantity.compareTo(totalAvailableQuantity) > 0) { |
| | | BigDecimal shortQuantity = deductQuantity.subtract(totalAvailableQuantity); |
| | | throw new ServiceException("颿å¯ç¨åºåä¸è¶³ï¼å¯ç¨åºå为" + formatQuantity(totalAvailableQuantity) |
| | | + "ï¼è¿å·®" + formatQuantity(shortQuantity)); |
| | | } |
| | | |
| | | BigDecimal remainingQuantity = deductQuantity; |
| | | for (Map.Entry<String, BigDecimal> entry : availableQuantityMap.entrySet()) { |
| | | if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | break; |
| | | } |
| | | BigDecimal availableQuantity = defaultDecimal(entry.getValue()); |
| | | if (availableQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | BigDecimal currentDeductQuantity = remainingQuantity.min(availableQuantity); |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setProductModelId(productModelId); |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | stockInventoryDto.setQualitity(quantity); |
| | | stockInventoryDto.setBatchNo(entry.getKey()); |
| | | stockInventoryDto.setQualitity(currentDeductQuantity); |
| | | int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto); |
| | | if (affected <= 0) { |
| | | throw new ServiceException("第" + rowNo + "æ¡é¢ææ£ååºå失败"); |
| | | } |
| | | remainingQuantity = remainingQuantity.subtract(currentDeductQuantity); |
| | | } |
| | | |
| | | if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) { |
| | | throw new ServiceException("第" + rowNo + "æ¡é¢ææ£ååºå失败ï¼å©ä½å¾
æ£åæ°é为" + formatQuantity(remainingQuantity)); |
| | | } |
| | | } |
| | | |
| | |
| | | if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, batchNo)); |
| | | if (stockInventory == null) { |
| | | StockInventory newStockInventory = new StockInventory(); |
| | | newStockInventory.setProductModelId(productModelId); |
| | | newStockInventory.setBatchNo(batchNo); |
| | | newStockInventory.setQualitity(addQuantity); |
| | | newStockInventory.setLockedQuantity(BigDecimal.ZERO); |
| | | newStockInventory.setVersion(1); |
| | | stockInventoryMapper.insert(newStockInventory); |
| | | return; |
| | | } |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setProductModelId(productModelId); |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | stockInventoryDto.setQualitity(addQuantity); |
| | | int affected = stockInventoryMapper.updateAddStockInventory(stockInventoryDto); |
| | | if (affected <= 0) { |
| | | throw new ServiceException("åºååé失败ï¼äº§åè§æ ¼ID=" + productModelId); |
| | | } |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PICK_RETURN_IN.getCode())); |
| | | stockInventoryDto.setRecordId(0L); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | |
| | | private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) { |
| | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private String formatQuantity(BigDecimal value) { |
| | | return defaultDecimal(value).stripTrailingZeros().toPlainString(); |
| | | } |
| | | } |
| | |
| | | ProductionOrderRoutingOperationParam query = dto == null ? new ProductionOrderRoutingOperationParam() : dto; |
| | | return Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .eq(query.getId() != null, ProductionOrderRoutingOperationParam::getId, query.getId()) |
| | | .eq(query.getProductionProductMainId() != null, |
| | | ProductionOrderRoutingOperationParam::getProductionProductMainId, query.getProductionProductMainId()) |
| | | .isNull(query.getProductionProductMainId() == null, |
| | | ProductionOrderRoutingOperationParam::getProductionProductMainId) |
| | | .eq(query.getProductionOrderId() != null, ProductionOrderRoutingOperationParam::getProductionOrderId, query.getProductionOrderId()) |
| | | .eq(query.getProductionOrderRoutingOperationId() != null, ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, query.getProductionOrderRoutingOperationId()) |
| | | .eq(query.getTechnologyOperationId() != null, |
| | |
| | | private void checkDuplicate(ProductionOrderRoutingOperationParam item) { |
| | | boolean duplicate = productionOrderRoutingOperationParamMapper.selectCount( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId) |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, item.getProductionOrderRoutingOperationId()) |
| | | .eq(item.getTechnologyRoutingOperationParamId() != null, |
| | | ProductionOrderRoutingOperationParam::getTechnologyRoutingOperationParamId, item.getTechnologyRoutingOperationParamId()) |
| | |
| | | import com.ruoyi.production.bean.vo.ProductionOrderPickVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderVo; |
| | | import com.ruoyi.production.bean.vo.ProductionPlanVo; |
| | | import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo; |
| | | import com.ruoyi.production.enums.ProductOrderStatusEnum; |
| | | import com.ruoyi.production.mapper.*; |
| | | import com.ruoyi.production.pojo.*; |
| | | import com.ruoyi.quality.mapper.QualityInspectFileMapper; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import com.ruoyi.quality.mapper.QualityInspectParamMapper; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityInspectFile; |
| | | import com.ruoyi.quality.pojo.QualityInspectParam; |
| | | import com.ruoyi.production.service.ProductionOrderService; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | |
| | | private final ProductionOrderBomMapper productionOrderBomMapper; |
| | | private final ProductionBomStructureMapper productionBomStructureMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | private final ProductionOrderPickMapper productionOrderPickMapper; |
| | | private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final QualityInspectParamMapper qualityInspectParamMapper; |
| | | private final QualityInspectFileMapper qualityInspectFileMapper; |
| | | private final ProductionPlanMapper productionPlanMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | private final StorageAttachmentMapper storageAttachmentMapper; |
| | |
| | | List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList( |
| | | Wrappers.<TechnologyRoutingOperation>lambdaQuery() |
| | | .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId()) |
| | | .orderByAsc(TechnologyRoutingOperation::getDragSort) |
| | | .orderByAsc(TechnologyRoutingOperation::getId)); |
| | | .orderByDesc(TechnologyRoutingOperation::getDragSort) |
| | | .orderByDesc(TechnologyRoutingOperation::getId)); |
| | | Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds( |
| | | routingOperations.stream() |
| | | .map(TechnologyRoutingOperation::getTechnologyOperationId) |
| | |
| | | .collect(Collectors.toSet())) |
| | | .stream() |
| | | .collect(Collectors.toMap(TechnologyOperation::getId, TechnologyOperation::getName, (a, b) -> a)); |
| | | Integer lastDragSort = routingOperations.stream() |
| | | .map(TechnologyRoutingOperation::getDragSort) |
| | | .filter(Objects::nonNull) |
| | | .max(Integer::compareTo) |
| | | .orElse(null); |
| | | for (TechnologyRoutingOperation sourceOperation : routingOperations) { |
| | | // 订åå·¥åºä¿åçæ¯å·¥èºå·¥åºå¿«ç
§ï¼åç»æ¥å·¥åªä¾èµå¿«ç
§ï¼ä¸åç´æ¥å¼ç¨å·¥èºä¸»æ°æ®ã |
| | | ProductionOrderRoutingOperation targetOperation = new ProductionOrderRoutingOperation(); |
| | |
| | | targetOperation.setOrderRoutingId(orderRouting.getId()); |
| | | targetOperation.setProductModelId(sourceOperation.getProductModelId()); |
| | | targetOperation.setDragSort(sourceOperation.getDragSort()); |
| | | targetOperation.setIsProduction(sourceOperation.getIsProduction()); |
| | | targetOperation.setIsQuality(sourceOperation.getIsQuality()); |
| | | targetOperation.setOperationName(operationNameMap.get(sourceOperation.getTechnologyOperationId())); |
| | | targetOperation.setTechnologyOperationId(sourceOperation.getTechnologyOperationId()); |
| | | productionOrderRoutingOperationMapper.insert(targetOperation); |
| | | |
| | | boolean isLastOperation = lastDragSort != null && Objects.equals(sourceOperation.getDragSort(), lastDragSort); |
| | | if (isLastOperation || Boolean.TRUE.equals(targetOperation.getIsProduction())) { |
| | | ProductionOperationTask task = new ProductionOperationTask(); |
| | | task.setProductionOrderRoutingOperationId(targetOperation.getId()); |
| | | task.setProductionOrderId(productionOrder.getId()); |
| | |
| | | task.setWorkOrderNo(generateNextTaskNo()); |
| | | task.setStatus(2); |
| | | productionOperationTaskMapper.insert(task); |
| | | } |
| | | |
| | | List<TechnologyRoutingOperationParam> sourceParams = technologyRoutingOperationParamMapper.selectList( |
| | | Wrappers.<TechnologyRoutingOperationParam>lambdaQuery() |
| | |
| | | } |
| | | |
| | | @Override |
| | | public ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(Long productionOrderId) { |
| | | if (productionOrderId == null) { |
| | | throw new ServiceException("productionOrderId can not be null"); |
| | | } |
| | | ProductionOrderVo orderInfo = getProductionOrderInfo(productionOrderId); |
| | | if (orderInfo == null) { |
| | | throw new ServiceException("production order not found"); |
| | | } |
| | | |
| | | ProductionOrderWorkOrderDetailVo detailVo = new ProductionOrderWorkOrderDetailVo(); |
| | | detailVo.setProductionOrder(orderInfo); |
| | | |
| | | List<ProductionOperationTask> workOrderList = productionOperationTaskMapper.selectList( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .eq(ProductionOperationTask::getProductionOrderId, productionOrderId) |
| | | .orderByAsc(ProductionOperationTask::getId)); |
| | | if (workOrderList == null || workOrderList.isEmpty()) { |
| | | detailVo.setWorkOrderList(Collections.emptyList()); |
| | | return detailVo; |
| | | } |
| | | |
| | | List<Long> workOrderIdList = workOrderList.stream() |
| | | .map(ProductionOperationTask::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | List<ProductionProductMain> reportMainList = workOrderIdList.isEmpty() |
| | | ? Collections.emptyList() |
| | | : productionProductMainMapper.selectList( |
| | | Wrappers.<ProductionProductMain>lambdaQuery() |
| | | .in(ProductionProductMain::getProductionOperationTaskId, workOrderIdList) |
| | | .orderByAsc(ProductionProductMain::getId)); |
| | | Map<Long, List<ProductionProductMain>> reportMainMap = new LinkedHashMap<>(); |
| | | for (ProductionProductMain reportMain : reportMainList) { |
| | | if (reportMain == null || reportMain.getProductionOperationTaskId() == null) { |
| | | continue; |
| | | } |
| | | reportMainMap.computeIfAbsent(reportMain.getProductionOperationTaskId(), k -> new ArrayList<>()).add(reportMain); |
| | | } |
| | | |
| | | List<Long> reportMainIdList = reportMainList.stream() |
| | | .map(ProductionProductMain::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | Map<Long, List<ProductionProductOutput>> reportOutputMap = new LinkedHashMap<>(); |
| | | Map<Long, List<ProductionOrderRoutingOperationParam>> reportParamMap = new LinkedHashMap<>(); |
| | | Map<Long, List<QualityInspect>> inspectMap = new LinkedHashMap<>(); |
| | | Map<Long, List<QualityInspectParam>> inspectParamMap = new LinkedHashMap<>(); |
| | | Map<Long, List<QualityInspectFile>> inspectFileMap = new LinkedHashMap<>(); |
| | | if (!reportMainIdList.isEmpty()) { |
| | | List<ProductionProductOutput> reportOutputList = productionProductOutputMapper.selectList( |
| | | Wrappers.<ProductionProductOutput>lambdaQuery() |
| | | .in(ProductionProductOutput::getProductionProductMainId, reportMainIdList) |
| | | .orderByAsc(ProductionProductOutput::getId)); |
| | | for (ProductionProductOutput reportOutput : reportOutputList) { |
| | | if (reportOutput == null) { |
| | | continue; |
| | | } |
| | | Long reportMainId = reportOutput.getProductionProductMainId() != null |
| | | ? reportOutput.getProductionProductMainId() |
| | | : reportOutput.getProductMainId(); |
| | | if (reportMainId == null) { |
| | | continue; |
| | | } |
| | | reportOutputMap.computeIfAbsent(reportMainId, k -> new ArrayList<>()).add(reportOutput); |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> reportParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, reportMainIdList) |
| | | .orderByAsc(ProductionOrderRoutingOperationParam::getId)); |
| | | for (ProductionOrderRoutingOperationParam reportParam : reportParamList) { |
| | | if (reportParam == null || reportParam.getProductionProductMainId() == null) { |
| | | continue; |
| | | } |
| | | reportParamMap.computeIfAbsent(reportParam.getProductionProductMainId(), k -> new ArrayList<>()).add(reportParam); |
| | | } |
| | | |
| | | List<QualityInspect> inspectList = qualityInspectMapper.selectList( |
| | | Wrappers.<QualityInspect>lambdaQuery() |
| | | .in(QualityInspect::getProductMainId, reportMainIdList) |
| | | .orderByAsc(QualityInspect::getId)); |
| | | for (QualityInspect inspect : inspectList) { |
| | | if (inspect == null || inspect.getProductMainId() == null) { |
| | | continue; |
| | | } |
| | | inspectMap.computeIfAbsent(inspect.getProductMainId(), k -> new ArrayList<>()).add(inspect); |
| | | } |
| | | |
| | | List<Long> inspectIdList = inspectList.stream() |
| | | .map(QualityInspect::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (!inspectIdList.isEmpty()) { |
| | | List<QualityInspectParam> inspectParamList = qualityInspectParamMapper.selectList( |
| | | Wrappers.<QualityInspectParam>lambdaQuery() |
| | | .in(QualityInspectParam::getInspectId, inspectIdList) |
| | | .orderByAsc(QualityInspectParam::getId)); |
| | | for (QualityInspectParam inspectParam : inspectParamList) { |
| | | if (inspectParam == null || inspectParam.getInspectId() == null) { |
| | | continue; |
| | | } |
| | | inspectParamMap.computeIfAbsent(inspectParam.getInspectId(), k -> new ArrayList<>()).add(inspectParam); |
| | | } |
| | | |
| | | List<QualityInspectFile> inspectFileList = qualityInspectFileMapper.selectList( |
| | | Wrappers.<QualityInspectFile>lambdaQuery() |
| | | .in(QualityInspectFile::getInspectId, inspectIdList) |
| | | .orderByAsc(QualityInspectFile::getId)); |
| | | for (QualityInspectFile inspectFile : inspectFileList) { |
| | | if (inspectFile == null || inspectFile.getInspectId() == null) { |
| | | continue; |
| | | } |
| | | inspectFileMap.computeIfAbsent(inspectFile.getInspectId(), k -> new ArrayList<>()).add(inspectFile); |
| | | } |
| | | } |
| | | } |
| | | |
| | | List<ProductionOrderWorkOrderDetailVo.WorkOrderDetail> workOrderDetailList = new ArrayList<>(); |
| | | for (ProductionOperationTask workOrder : workOrderList) { |
| | | ProductionOrderWorkOrderDetailVo.WorkOrderDetail workOrderDetail = new ProductionOrderWorkOrderDetailVo.WorkOrderDetail(); |
| | | workOrderDetail.setWorkOrder(workOrder); |
| | | |
| | | List<ProductionProductMain> workOrderReportMainList = reportMainMap.get(workOrder.getId()); |
| | | if (workOrderReportMainList == null || workOrderReportMainList.isEmpty()) { |
| | | workOrderDetail.setReportList(Collections.emptyList()); |
| | | workOrderDetailList.add(workOrderDetail); |
| | | continue; |
| | | } |
| | | |
| | | List<ProductionOrderWorkOrderDetailVo.ReportDetail> reportDetailList = new ArrayList<>(); |
| | | for (ProductionProductMain reportMain : workOrderReportMainList) { |
| | | Long reportMainId = reportMain.getId(); |
| | | ProductionOrderWorkOrderDetailVo.ReportDetail reportDetail = new ProductionOrderWorkOrderDetailVo.ReportDetail(); |
| | | reportDetail.setReportMain(reportMain); |
| | | reportDetail.setReportOutputList(reportOutputMap.getOrDefault(reportMainId, Collections.emptyList())); |
| | | reportDetail.setReportParamList(reportParamMap.getOrDefault(reportMainId, Collections.emptyList())); |
| | | |
| | | List<QualityInspect> reportInspectList = inspectMap.get(reportMainId); |
| | | if (reportInspectList == null || reportInspectList.isEmpty()) { |
| | | reportDetail.setInspectList(Collections.emptyList()); |
| | | } else { |
| | | List<ProductionOrderWorkOrderDetailVo.InspectDetail> inspectDetailList = new ArrayList<>(); |
| | | for (QualityInspect inspect : reportInspectList) { |
| | | ProductionOrderWorkOrderDetailVo.InspectDetail inspectDetail = new ProductionOrderWorkOrderDetailVo.InspectDetail(); |
| | | inspectDetail.setInspect(inspect); |
| | | inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList())); |
| | | inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList())); |
| | | inspectDetailList.add(inspectDetail); |
| | | } |
| | | reportDetail.setInspectList(inspectDetailList); |
| | | } |
| | | reportDetailList.add(reportDetail); |
| | | } |
| | | workOrderDetail.setReportList(reportDetailList); |
| | | workOrderDetailList.add(workOrderDetail); |
| | | } |
| | | |
| | | detailVo.setWorkOrderList(workOrderDetailList); |
| | | return detailVo; |
| | | } |
| | | |
| | | @Override |
| | | public List<ProductionOrderPickVo> pick(Long productionOrderId) { |
| | | if (productionOrderId == null) { |
| | | return Collections.emptyList(); |
| | |
| | | } |
| | | return new ArrayList<>(mergedPickMap.values()); |
| | | } |
| | | |
| | | @Override |
| | | public int updateOrder(ProductionOrderDto productionOrderDto) { |
| | | productionOrderDto.setStatus(5); |
| | | return baseMapper.updateById(productionOrderDto); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.quality.mapper.*; |
| | | import com.ruoyi.quality.pojo.*; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyOperation; |
| | |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final StockUtils stockUtils; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | @Override |
| | | public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) { |
| | | return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); |
| | | IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto); |
| | | fillOperationParamList(result.getRecords()); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public ProductionProductMainDto getProductionProductMainInfo(Long id) { |
| | | return productionProductMainMapper.listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{ |
| | | return listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{ |
| | | setId(id); |
| | | }}).getRecords().stream().findFirst().orElse(null); |
| | | } |
| | | |
| | | private void fillOperationParamList(List<ProductionProductMainDto> recordList) { |
| | | if (recordList == null || recordList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> mainIdSet = recordList.stream() |
| | | .map(ProductionProductMainDto::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (mainIdSet.isEmpty()) { |
| | | recordList.forEach(item -> item.setProductionOperationParamList(Collections.emptyList())); |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> paramList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, mainIdSet) |
| | | .orderByAsc(ProductionOrderRoutingOperationParam::getId)); |
| | | Map<Long, List<ProductionOrderRoutingOperationParam>> paramGroupMap = new HashMap<>(); |
| | | for (ProductionOrderRoutingOperationParam param : paramList) { |
| | | if (param == null || param.getProductionProductMainId() == null) { |
| | | continue; |
| | | } |
| | | paramGroupMap.computeIfAbsent(param.getProductionProductMainId(), key -> new ArrayList<>()).add(param); |
| | | } |
| | | |
| | | Set<Long> missingMainIdSet = new LinkedHashSet<>(); |
| | | for (ProductionProductMainDto item : recordList) { |
| | | Long mainId = item.getId(); |
| | | if (mainId == null) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | continue; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> params = paramGroupMap.get(mainId); |
| | | if (params != null && !params.isEmpty()) { |
| | | item.setProductionOperationParamList(params); |
| | | continue; |
| | | } |
| | | missingMainIdSet.add(mainId); |
| | | } |
| | | if (missingMainIdSet.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // å
¼å®¹å岿°æ®ï¼æ§æ¥å·¥è®°å½æ²¡æææ¥å·¥IDè½åæ°å¿«ç
§æ¶ï¼åéå±ç¤ºå·¥åºæ¨¡æ¿åæ°ã |
| | | List<ProductionProductMain> mainList = productionProductMainMapper.selectBatchIds(missingMainIdSet); |
| | | Map<Long, Long> mainIdToTaskIdMap = mainList.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionProductMain::getId, |
| | | ProductionProductMain::getProductionOperationTaskId, (left, right) -> left)); |
| | | Set<Long> taskIdSet = mainIdToTaskIdMap.values().stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (taskIdSet.isEmpty()) { |
| | | for (ProductionProductMainDto item : recordList) { |
| | | if (item.getId() != null && missingMainIdSet.contains(item.getId())) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .in(ProductionOperationTask::getId, taskIdSet)); |
| | | Map<Long, Long> taskIdToRoutingOperationIdMap = taskList.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionOperationTask::getId, |
| | | ProductionOperationTask::getProductionOrderRoutingOperationId, (left, right) -> left)); |
| | | Set<Long> routingOperationIdSet = taskIdToRoutingOperationIdMap.values().stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (routingOperationIdSet.isEmpty()) { |
| | | for (ProductionProductMainDto item : recordList) { |
| | | if (item.getId() != null && missingMainIdSet.contains(item.getId())) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> fallbackParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperationIdSet) |
| | | .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId) |
| | | .orderByAsc(ProductionOrderRoutingOperationParam::getId)); |
| | | Map<Long, List<ProductionOrderRoutingOperationParam>> fallbackGroupMap = new HashMap<>(); |
| | | for (ProductionOrderRoutingOperationParam param : fallbackParamList) { |
| | | if (param == null || param.getProductionOrderRoutingOperationId() == null) { |
| | | continue; |
| | | } |
| | | fallbackGroupMap.computeIfAbsent(param.getProductionOrderRoutingOperationId(), key -> new ArrayList<>()).add(param); |
| | | } |
| | | |
| | | for (ProductionProductMainDto item : recordList) { |
| | | Long mainId = item.getId(); |
| | | if (mainId == null || !missingMainIdSet.contains(mainId)) { |
| | | continue; |
| | | } |
| | | Long taskId = mainIdToTaskIdMap.get(mainId); |
| | | Long routingOperationId = taskId == null ? null : taskIdToRoutingOperationIdMap.get(taskId); |
| | | if (routingOperationId == null) { |
| | | item.setProductionOperationParamList(Collections.emptyList()); |
| | | continue; |
| | | } |
| | | item.setProductionOperationParamList(fallbackGroupMap.getOrDefault(routingOperationId, Collections.emptyList())); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (productionOrder == null) { |
| | | throw new ServiceException("ç产订åä¸åå¨"); |
| | | } |
| | | syncOperationParamInputValue(dto, routingOperation.getId()); |
| | | TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()); |
| | | TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null |
| | | : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); |
| | |
| | | productionProductMain.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); |
| | | |
| | | List<ProductStructureDto> productStructureDtos = resolveInputStructures( |
| | | productionOrder.getId(), routingOperation, productModel.getId()); |
| | | // å¦ææ²¡æbomåèç¹äºï¼é£ä¹æå
¥å°±æ¯ä»æ¬èº« |
| | | if (productStructureDtos.isEmpty()) { |
| | | throw new ServiceException("æªæ¾å°å½åå·¥åºå¯¹åºçBOMæå
¥èç¹"); |
| | | ProductStructureDto fallbackInput = new ProductStructureDto(); |
| | | fallbackInput.setProductModelId(productModel.getId()); |
| | | fallbackInput.setUnitQuantity(BigDecimal.ONE); |
| | | productStructureDtos.add(fallbackInput); |
| | | } |
| | | for (ProductStructureDto item : productStructureDtos) { |
| | | // å½åå®ç°æå·¥åºæåç´æ¥ä½ä¸ºæå
¥ï¼åç»è¥æ¥å
¥é¢æè®°å½å¯å¨è¿éæ¿æ¢æ¥æºã |
| | |
| | | productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity())); |
| | | productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty())); |
| | | productionProductOutputMapper.insert(productionProductOutput); |
| | | BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty()); |
| | | BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity()); |
| | | BigDecimal productQty = reportQty; |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | |
| | | qualityInspect.setProductModelId(productModel.getId()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process); |
| | | if (qualityTestStandard.size() > 0) { |
| | | if (!qualityTestStandard.isEmpty()) { |
| | | qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery() |
| | |
| | | }); |
| | | } |
| | | } else { |
| | | stockUtils.addStock(productModel.getId(), productQty, |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId()); |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordId(productionProductMain.getId()); |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode())); |
| | | stockInventoryDto.setQualitity(productQty); |
| | | stockInventoryDto.setProductModelId(productModel.getId()); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty)); |
| | |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), |
| | | StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId()); |
| | | } |
| | | // if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) { |
| | | // stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), |
| | | // StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId()); |
| | | // } |
| | | return true; |
| | | } |
| | | |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, Long productionOrderRoutingOperationId) { |
| | | if (dto == null || productionOrderRoutingOperationId == null) { |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, |
| | | Long productionOrderRoutingOperationId, |
| | | Long productionProductMainId) { |
| | | if (dto == null || productionOrderRoutingOperationId == null || productionProductMainId == null) { |
| | | return; |
| | | } |
| | | List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList(); |
| | | if (paramList == null || paramList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> sourceParamIdSet = paramList.stream() |
| | | .filter(Objects::nonNull) |
| | | .map(ProductionOrderRoutingOperationParam::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (sourceParamIdSet.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .in(ProductionOrderRoutingOperationParam::getId, sourceParamIdSet) |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, productionOrderRoutingOperationId)); |
| | | if (dbParamList == null || dbParamList.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | Map<Long, ProductionOrderRoutingOperationParam> dbParamMap = dbParamList.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionOrderRoutingOperationParam::getId, item -> item, (left, right) -> left)); |
| | |
| | | if (dbParam == null) { |
| | | throw new ServiceException("å·¥åºåæ°ä¸å卿ä¸å±äºå½åå·¥åå·¥åºï¼ID=" + param.getId()); |
| | | } |
| | | if (Objects.equals(dbParam.getInputValue(), param.getInputValue())) { |
| | | continue; |
| | | productionOrderRoutingOperationParamMapper.insert(buildReportParamSnapshot(dbParam, param.getInputValue(), productionProductMainId)); |
| | | } |
| | | ProductionOrderRoutingOperationParam updateParam = new ProductionOrderRoutingOperationParam(); |
| | | updateParam.setId(dbParam.getId()); |
| | | updateParam.setInputValue(param.getInputValue()); |
| | | productionOrderRoutingOperationParamMapper.updateById(updateParam); |
| | | } |
| | | |
| | | private ProductionOrderRoutingOperationParam buildReportParamSnapshot(ProductionOrderRoutingOperationParam source, |
| | | String inputValue, |
| | | Long productionProductMainId) { |
| | | ProductionOrderRoutingOperationParam target = new ProductionOrderRoutingOperationParam(); |
| | | target.setProductionOrderId(source.getProductionOrderId()); |
| | | target.setTechnologyRoutingOperationParamId(source.getTechnologyRoutingOperationParamId()); |
| | | target.setParamCode(source.getParamCode()); |
| | | target.setParamName(source.getParamName()); |
| | | target.setParamType(source.getParamType()); |
| | | target.setParamFormat(source.getParamFormat()); |
| | | target.setUnit(source.getUnit()); |
| | | target.setIsRequired(source.getIsRequired()); |
| | | target.setRemark(source.getRemark()); |
| | | target.setParamId(source.getParamId()); |
| | | target.setTechnologyOperationId(source.getTechnologyOperationId()); |
| | | target.setTechnologyOperationParamId(source.getTechnologyOperationParamId()); |
| | | target.setStandardValue(source.getStandardValue()); |
| | | target.setInputValue(inputValue); |
| | | target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId()); |
| | | target.setProductionProductMainId(productionProductMainId); |
| | | return target; |
| | | } |
| | | |
| | | private List<ProductStructureDto> resolveInputStructures(Long productionOrderId, |
| | |
| | | |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId()); |
| | | if (productionOperationTask != null && productionProductOutput != null) { |
| | | BigDecimal validQuantity = defaultDecimal(productionProductOutput.getQuantity()).subtract(defaultDecimal(productionProductOutput.getScrapQty())); |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(validQuantity)); |
| | | BigDecimal reportQuantity = defaultDecimal(productionProductOutput.getQuantity()); |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(reportQuantity)); |
| | | productionOperationTask.setActualEndTime(null); |
| | | if (defaultDecimal(productionOperationTask.getCompleteQuantity()).compareTo(BigDecimal.ZERO) <= 0) { |
| | | productionOperationTask.setCompleteQuantity(BigDecimal.ZERO); |
| | |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); |
| | | boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); |
| | | if (isLastOperation) { |
| | | BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(validQuantity); |
| | | BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(reportQuantity); |
| | | productionOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty); |
| | | productionOrder.setEndTime(null); |
| | | } |
| | |
| | | .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId())); |
| | | productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>() |
| | | .eq(ProductionProductInput::getProductionProductMainId, productionProductMain.getId())); |
| | | productionOrderRoutingOperationParamMapper.delete( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionProductMainId, productionProductMain.getId())); |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode()); |
| | | stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()); |
| | | stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode()); |
| | |
| | | import io.swagger.v3.oas.annotations.tags.Tag;
|
| | | import jakarta.servlet.http.HttpServletResponse;
|
| | | import lombok.AllArgsConstructor;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.core.io.FileSystemResource;
|
| | | import org.springframework.http.ContentDisposition;
|
| | | import org.springframework.http.MediaType;
|
| | |
| | | @RestController
|
| | | @RequestMapping("/common")
|
| | | public class CommonController {
|
| | | private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
| | |
|
| | |
|
| | | private final StorageBlobService storageBlobService;
|
| | | private final FileUtil fileUtil;
|
| | |
|
| | |
|
| | | // /**
|
| | | // * éç¨ä¸è½½è¯·æ±
|
| | | // *
|
| | | // * @param fileName æä»¶åç§°
|
| | | // * @param delete æ¯å¦å é¤
|
| | | // */
|
| | | // @GetMapping("/download")
|
| | | // public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
|
| | | // {
|
| | | // try
|
| | | // {
|
| | | // if (!FileUtils.checkAllowDownload(fileName))
|
| | | // {
|
| | | // throw new Exception(StringUtils.format("æä»¶åç§°({})éæ³ï¼ä¸å
许ä¸è½½ã ", fileName));
|
| | | // }
|
| | | // String realFileName = fileName.substring(fileName.indexOf("_") + 1);
|
| | | //
|
| | | // response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
| | | // FileUtils.setAttachmentResponseHeader(response, realFileName);
|
| | | // FileUtils.writeBytes(fileName, response.getOutputStream());
|
| | |
|
| | | /// / if (delete)
|
| | | /// / {
|
| | | /// / FileUtils.deleteFile(fileName);
|
| | | /// / }
|
| | | // }
|
| | | // catch (Exception e)
|
| | | // {
|
| | | // log.error("ä¸è½½æä»¶å¤±è´¥", e);
|
| | | // }
|
| | | // }
|
| | | //
|
| | | // /**
|
| | | // * éç¨ä¸ä¼ 请æ±ï¼å个ï¼
|
| | | // */
|
| | | // @PostMapping("/upload")
|
| | | // public AjaxResult uploadFile(MultipartFile file) throws Exception
|
| | | // {
|
| | | // try
|
| | | // {
|
| | | // // ä¸ä¼ æä»¶è·¯å¾
|
| | | // String filePath = RuoYiConfig.getUploadPath();
|
| | | // // ä¸ä¼ å¹¶è¿åæ°æä»¶åç§°
|
| | | // String fileName = FileUploadUtils.upload(filePath, file);
|
| | | // String url = serverConfig.getUrl() + fileName;
|
| | | // AjaxResult ajax = AjaxResult.success();
|
| | | // ajax.put("url", url);
|
| | | // ajax.put("fileName", fileName);
|
| | | // ajax.put("newFileName", FileUtils.getName(fileName));
|
| | | // ajax.put("originalFilename", file.getOriginalFilename());
|
| | | // return ajax;
|
| | | // }
|
| | | // catch (Exception e)
|
| | | // {
|
| | | // return AjaxResult.error(e.getMessage());
|
| | | // }
|
| | | // }
|
| | | //
|
| | | // /**
|
| | | // * æ¬å°èµæºéç¨ä¸è½½
|
| | | // */
|
| | | // @GetMapping("/download/resource")
|
| | | // public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
|
| | | // throws Exception
|
| | | // {
|
| | | // try
|
| | | // {
|
| | | // if (!FileUtils.checkAllowDownload(resource))
|
| | | // {
|
| | | // throw new Exception(StringUtils.format("èµæºæä»¶({})éæ³ï¼ä¸å
许ä¸è½½ã ", resource));
|
| | | // }
|
| | | // // æ¬å°èµæºè·¯å¾
|
| | | // String localPath = RuoYiConfig.getProfile();
|
| | | // // æ°æ®åºèµæºå°å
|
| | | // String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
| | | // // ä¸è½½åç§°
|
| | | // String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
| | | // response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
| | | // FileUtils.setAttachmentResponseHeader(response, downloadName);
|
| | | // FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
| | | // }
|
| | | // catch (Exception e)
|
| | | // {
|
| | | // log.error("ä¸è½½æä»¶å¤±è´¥", e);
|
| | | // }
|
| | | // }
|
| | | @PostMapping({"/upload"})
|
| | | @Operation(summary = "æä»¶ä¸ä¼ ")
|
| | | public R upload(@RequestParam("files") List<MultipartFile> files) {
|
| | |
| | | import com.ruoyi.purchase.pojo.InvoicePurchase; |
| | | import com.ruoyi.purchase.service.IInvoicePurchaseService; |
| | | import com.ruoyi.sales.service.ICommonFileService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | |
| | | return toAjax(invoicePurchaseService.delInvoice(ids)); |
| | | } |
| | | |
| | | @PostMapping("/upload") |
| | | public AjaxResult uploadFile(MultipartFile file, Long id, Integer type) { |
| | | try { |
| | | return AjaxResult.success(commonFileService.uploadFile(file, id, type)); |
| | | } catch (Exception e) { |
| | | return AjaxResult.error(e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.purchase.service.ITicketRegistrationService; |
| | | import com.ruoyi.purchase.service.impl.PaymentRegistrationServiceImpl; |
| | | import com.ruoyi.sales.service.ICommonFileService; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.core.parameters.P; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult delRegistration(@RequestBody Long[] ids) { |
| | | return toAjax(ticketRegistrationService.delRegistration(ids)); |
| | | } |
| | | |
| | | @PostMapping("/upload") |
| | | public AjaxResult uploadFile(MultipartFile file, Long id, Integer type) { |
| | | try { |
| | | return AjaxResult.success(commonFileService.uploadFile(file, id, type)); |
| | | } catch (Exception e) { |
| | | return AjaxResult.error(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | |
| | | private String templateName; |
| | | @Schema(description = "审æ¹äººid") |
| | | private Integer approverId; |
| | | |
| | | private List<StorageBlobVO> storageBlobVOS; |
| | | private List<StorageBlobDTO> storageBlobDTOS; |
| | | } |
| | |
| | | |
| | | private final CommonFileMapper commonFileMapper; |
| | | |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | @Override |
| | | public List<InvoicePurchaseDto> selectInvoicePurchaseList(InvoicePurchaseDto invoicePurchaseDto) { |
| | |
| | | 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.ApproveProcessVO; |
| | | import com.ruoyi.approve.pojo.ApproveProcess; |
| | | import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl; |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessVO; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.mapper.SupplierManageMapper; |
| | | import com.ruoyi.basic.pojo.Product; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.pojo.SupplierManage; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | |
| | | import com.ruoyi.sales.service.impl.CommonFileServiceImpl; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | |
| | | private final QualityInspectParamMapper qualityInspectParamMapper; |
| | | private final ApproveProcessServiceImpl approveProcessService; |
| | | private final ProcurementRecordMapper procurementRecordStorageMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | private final FileUtil fileUtil; |
| | | |
| | | @Override |
| | | public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { |
| | |
| | | // } |
| | | // } |
| | | // 5. è¿ç§»ä¸´æ¶æä»¶å°æ£å¼ç®å½ |
| | | if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) { |
| | | migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds()); |
| | | } |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId(), purchaseLedgerDto.getStorageBlobDTOS()); |
| | | return 1; |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | fileRecord.setType(FileNameType.PURCHASE.getValue()); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // å é¤ä¸´æ¶æä»¶è®°å½ |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int deletePurchaseLedgerByIds(Long[] ids) { |
| | |
| | | .eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType()); |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); |
| | | |
| | | // 3.æ¥è¯¢ä¸ä¼ æä»¶ |
| | | LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerFileWrapper.eq(CommonFile::getCommonId, purchaseLedger.getId()) |
| | | .eq(CommonFile::getType,FileNameType.PURCHASE.getValue()); |
| | | List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper); |
| | | |
| | | // 4. è½¬æ¢ DTO |
| | | PurchaseLedgerDto resultDto = new PurchaseLedgerDto(); |
| | |
| | | if (!products.isEmpty()) { |
| | | resultDto.setHasChildren(true); |
| | | resultDto.setProductData(products); |
| | | resultDto.setSalesLedgerFiles(salesLedgerFiles); |
| | | resultDto.setStorageBlobVOS(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId())); |
| | | } |
| | | return resultDto; |
| | | } |
| | |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.purchase.dto.PaymentRegistrationDto; |
| | | import com.ruoyi.purchase.dto.PurchaseLedgerDto; |
| | | import com.ruoyi.purchase.dto.TicketRegistrationDto; |
| | |
| | | import com.ruoyi.sales.service.ISalesLedgerProductService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | private final ISalesLedgerProductService salesLedgerProductService; |
| | | |
| | | private final PaymentRegistrationMapper paymentRegistrationMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | |
| | | @Override |
| | |
| | | throw new RuntimeException("产åå¼ç¥¨æ°é½ä¸º0ï¼è¯·æ£æ¥"); |
| | | } |
| | | } |
| | | // è¿ç§»ä¸´æ¶æä»¶å°æ£å¼ç®å½ |
| | | if (ticketRegistrationDto.getTempFileIds() != null && !ticketRegistrationDto.getTempFileIds().isEmpty()) { |
| | | migrateTempFilesToFormal(ticketRegistration.getId(), ticketRegistrationDto.getTempFileIds()); |
| | | } |
| | | return rowsAffected; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String baseName = FilenameUtils.getBaseName(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) +baseName+ |
| | | (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | fileRecord.setType(4); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.config.Configure; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.utils.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.procurementrecord.service.ProcurementRecordService; |
| | |
| | | import com.ruoyi.quality.service.IQualityInspectParamService; |
| | | import com.ruoyi.quality.service.IQualityInspectService; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | |
| | | public class QualityInspectServiceImpl extends ServiceImpl<QualityInspectMapper, QualityInspect> implements IQualityInspectService { |
| | | |
| | | private final StockUtils stockUtils; |
| | | private final StockInventoryService stockInventoryService; |
| | | private QualityInspectMapper qualityInspectMapper; |
| | | |
| | | private IQualityInspectParamService qualityInspectParamService; |
| | |
| | | qualityUnqualifiedMapper.insert(qualityUnqualified); |
| | | } else { |
| | | //åæ ¼ç´æ¥å
¥åº |
| | | stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId()); |
| | | // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId()); |
| | | //ä»
æ·»å å
¥åºè®°å½ |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode())); |
| | | stockInventoryDto.setRecordId(qualityInspect.getId()); |
| | | stockInventoryDto.setProductModelId(qualityInspect.getProductModelId()); |
| | | stockInventoryDto.setQualitity(qualityInspect.getQuantity()); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | qualityInspect.setInspectState(1);//å·²æäº¤ |
| | | return qualityInspectMapper.updateById(qualityInspect); |
| | |
| | | @RequiredArgsConstructor |
| | | public class SafeTrainingController { |
| | | |
| | | private SafeTrainingService safeTrainingService; |
| | | private SafeTrainingDetailsService safeTrainingDetailsService; |
| | | private final SafeTrainingService safeTrainingService; |
| | | private final SafeTrainingDetailsService safeTrainingDetailsService; |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "å页æ¥è¯¢") |
| | |
| | | package com.ruoyi.sales.service; |
| | | |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | public interface ICommonFileService { |
| | | |
| | | int deleteSalesLedgerByIds(Long[] ids); |
| | | |
| | | CommonFile uploadFile(MultipartFile file, Long id, Integer type) throws IOException; |
| | | |
| | | int delCommonFileByIds(Long[] ids); |
| | | } |
| | |
| | | package com.ruoyi.sales.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.sales.mapper.CommonFileMapper; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import com.ruoyi.sales.service.ICommonFileService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.UUID; |
| | | |
| | | @Service |
| | | @RequiredArgsConstructor |
| | |
| | | private final CommonFileMapper commonFileMapper; |
| | | |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | public List<CommonFile> getFileListByBusinessId(Long businessId,Integer type) { |
| | | return commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, businessId) |
| | |
| | | return commonFileMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | } |
| | | |
| | | @Override |
| | | public CommonFile uploadFile(MultipartFile file, Long id, Integer type) throws IOException { |
| | | // 1. çææ£å¼æä»¶IDåè·¯å¾ |
| | | String tempId = UUID.randomUUID().toString(); |
| | | Path tempFilePath = Paths.get(uploadDir, tempId + "_" + file.getOriginalFilename()); |
| | | |
| | | // 2. ç¡®ä¿ç®å½åå¨ |
| | | Path parentDir = tempFilePath.getParent(); |
| | | if (parentDir != null) { |
| | | Files.createDirectories(parentDir); // éå½å建ç®å½ |
| | | } |
| | | |
| | | // 3. ä¿åæä»¶å°ç®å½ |
| | | file.transferTo(tempFilePath.toFile()); |
| | | |
| | | // 4. ä¿åæä»¶è®°å½ |
| | | CommonFile commonFile = new CommonFile(); |
| | | commonFile.setCommonId(id); |
| | | commonFile.setName(file.getOriginalFilename()); |
| | | commonFile.setUrl(tempFilePath.toString()); |
| | | commonFile.setType(type); |
| | | commonFileMapper.insert(commonFile); |
| | | return commonFile; |
| | | } |
| | | |
| | | @Override |
| | | public int delCommonFileByIds(Long[] ids) { |
| | | return commonFileMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | } |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | fileRecord.setType(tempFile.getType()); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.production.mapper.ProductionProductInputMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductOutputMapper; |
| | |
| | | import com.ruoyi.sales.vo.SalesLedgerVo; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.jetbrains.annotations.Nullable; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.lang.reflect.Field; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.YearMonth; |
| | |
| | | private static final String LOCK_PREFIX = "contract_no_lock:"; |
| | | private static final long LOCK_WAIT_TIMEOUT = 10; // éçå¾
è¶
æ¶æ¶é´ï¼ç§ï¼ |
| | | private static final long LOCK_EXPIRE_TIME = 30; // éèªå¨è¿ææ¶é´ï¼ç§ï¼ |
| | | private final AccountIncomeService accountIncomeService; |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final CustomerMapper customerMapper; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl; |
| | | private final CommonFileMapper commonFileMapper; |
| | | private final TempFileMapper tempFileMapper; |
| | | private final ReceiptPaymentMapper receiptPaymentMapper; |
| | | private final ShippingInfoServiceImpl shippingInfoServiceImpl; |
| | | private final CommonFileServiceImpl commonFileService; |
| | |
| | | private final InvoiceLedgerMapper invoiceLedgerMapper; |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | private final InvoiceRegistrationMapper invoiceRegistrationMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final ProductModelMapper productModelMapper; |
| | | private final RedisTemplate<String, String> redisTemplate; |
| | | private final SysDeptMapper sysDeptMapper; |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | private final ProductionProductMainService productionProductMainService; |
| | | private final PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper; |
| | | private final SysUserMapper sysUserMapper; |
| | |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, salesLedger.getId(), salesLedgerDto.getStorageBlobDTOs()); |
| | | } |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | //éå® |
| | | fileRecord.setType(FileNameType.SALE.getValue()); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // å é¤ä¸´æ¶æä»¶è®°å½ |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æä»¶è¿ç§»æ¹æ³ |
| | |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.other.service.impl.TempFileServiceImpl; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.sales.dto.SalesLedgerProductDto; |
| | | import com.ruoyi.sales.dto.ShippingInfoDto; |
| | |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.Collections; |
| | |
| | | |
| | | private final ShippingInfoMapper shippingInfoMapper; |
| | | |
| | | private final TempFileServiceImpl tempFileService; |
| | | |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.R; |
| | |
| | | import com.ruoyi.stock.dto.StockUninventoryDto; |
| | | import com.ruoyi.stock.execl.StockInventoryExportData; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.pojo.StockInventory; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import com.ruoyi.stock.service.StockOutRecordService; |
| | | import com.ruoyi.stock.service.StockUninventoryService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | |
| | | private StockOutRecordService stockOutRecordService; |
| | | private StockUninventoryService stockUninventoryService; |
| | | private SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private ProductModelMapper productModelMapper; |
| | | @Override |
| | | public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) { |
| | | return stockInventoryMapper.pagestockInventory(page, stockInventoryDto); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addstockInventory(StockInventoryDto stockInventoryDto) { |
| | | String batchNo = StringUtils.trim(stockInventoryDto.getBatchNo()); |
| | | if (StringUtils.isEmpty(batchNo)) { |
| | | batchNo = generateAutoBatchNo(stockInventoryDto.getProductModelId()); |
| | | } |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | |
| | | LambdaQueryWrapper<StockInventory> eq = new QueryWrapper<StockInventory>().lambda() |
| | | .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()); |
| | | if (StringUtils.isEmpty(stockInventoryDto.getBatchNo())) { |
| | | eq.isNull(StockInventory::getBatchNo); |
| | | stockInventoryDto.setBatchNo(null); |
| | | } else { |
| | | eq.eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo()); |
| | | } |
| | | //æ°å¢å
¥åºè®°å½åæ·»å åºå |
| | | StockInRecordDto stockInRecordDto = new StockInRecordDto(); |
| | | stockInRecordDto.setRecordId(stockInventoryDto.getRecordId()); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addStockInRecordOnly(StockInventoryDto stockInventoryDto) { |
| | | String batchNo = StringUtils.trim(stockInventoryDto.getBatchNo()); |
| | | if (StringUtils.isEmpty(batchNo)) { |
| | | batchNo = generateAutoBatchNo(stockInventoryDto.getProductModelId()); |
| | | } |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | |
| | | StockInRecordDto stockInRecordDto = new StockInRecordDto(); |
| | | stockInRecordDto.setRecordId(stockInventoryDto.getRecordId()); |
| | | stockInRecordDto.setRecordType(stockInventoryDto.getRecordType()); |
| | | stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity()); |
| | | stockInRecordDto.setBatchNo(stockInventoryDto.getBatchNo()); |
| | | stockInRecordDto.setBatchNo(batchNo); |
| | | stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId()); |
| | | stockInRecordDto.setType("0"); |
| | | stockInRecordDto.setRemark(stockInventoryDto.getRemark()); |
| | |
| | | return true; |
| | | } |
| | | |
| | | //è§åçæï¼20260424-产åç¼å·-001 |
| | | private String generateAutoBatchNo(Long productModelId) { |
| | | if (productModelId == null) { |
| | | throw new ServiceException("产åè§æ ¼IDä¸è½ä¸ºç©º"); |
| | | } |
| | | ProductModel productModel = productModelMapper.selectById(productModelId); |
| | | if (productModel == null) { |
| | | throw new ServiceException("产åè§æ ¼ä¸åå¨ï¼ID=" + productModelId); |
| | | } |
| | | String productCode = StringUtils.trim(productModel.getProductCode()); |
| | | if (StringUtils.isEmpty(productCode)) { |
| | | throw new ServiceException("产åè§æ ¼æªç»´æ¤äº§åç¼ç ï¼ID=" + productModelId); |
| | | } |
| | | |
| | | String dateText = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); |
| | | String prefix = dateText + "-" + productCode + "-"; |
| | | int maxSequence = resolveMaxSequence(prefix); |
| | | int sequence = maxSequence + 1; |
| | | while (sequence < 1_000_000) { |
| | | String batchNo = prefix + String.format("%03d", sequence); |
| | | if (!isBatchNoExists(batchNo)) { |
| | | return batchNo; |
| | | } |
| | | sequence++; |
| | | } |
| | | throw new ServiceException("æ¹å·åºå·è¶
åºèå´ï¼è¯·æ£æ¥æ¹å·æ°æ®"); |
| | | } |
| | | |
| | | private int resolveMaxSequence(String prefix) { |
| | | int maxSequence = 0; |
| | | List<StockInventory> stockInventoryList = stockInventoryMapper.selectList( |
| | | Wrappers.<StockInventory>lambdaQuery() |
| | | .select(StockInventory::getBatchNo) |
| | | .likeRight(StockInventory::getBatchNo, prefix)); |
| | | for (StockInventory stockInventory : stockInventoryList) { |
| | | maxSequence = Math.max(maxSequence, parseSequence(stockInventory.getBatchNo(), prefix)); |
| | | } |
| | | |
| | | List<StockInRecord> stockInRecordList = stockInRecordService.list( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .select(StockInRecord::getBatchNo) |
| | | .likeRight(StockInRecord::getBatchNo, prefix)); |
| | | for (StockInRecord stockInRecord : stockInRecordList) { |
| | | maxSequence = Math.max(maxSequence, parseSequence(stockInRecord.getBatchNo(), prefix)); |
| | | } |
| | | return maxSequence; |
| | | } |
| | | |
| | | private int parseSequence(String batchNo, String prefix) { |
| | | if (StringUtils.isEmpty(batchNo) || StringUtils.isEmpty(prefix) || !batchNo.startsWith(prefix)) { |
| | | return 0; |
| | | } |
| | | String sequenceText = batchNo.substring(prefix.length()); |
| | | if (StringUtils.isEmpty(sequenceText) || !sequenceText.matches("\\d+")) { |
| | | return 0; |
| | | } |
| | | try { |
| | | return Integer.parseInt(sequenceText); |
| | | } catch (NumberFormatException ignored) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private boolean isBatchNoExists(String batchNo) { |
| | | if (StringUtils.isEmpty(batchNo)) { |
| | | return false; |
| | | } |
| | | Long inventoryCount = stockInventoryMapper.selectCount( |
| | | Wrappers.<StockInventory>lambdaQuery().eq(StockInventory::getBatchNo, batchNo)); |
| | | if (inventoryCount != null && inventoryCount > 0) { |
| | | return true; |
| | | } |
| | | return stockInRecordService.count( |
| | | Wrappers.<StockInRecord>lambdaQuery().eq(StockInRecord::getBatchNo, batchNo)) > 0; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addStockOutRecordOnly(StockInventoryDto stockInventoryDto) { |
| | |
| | | /** |
| | | * ä¿®æ¹å·¥èºè·¯çº¿ã |
| | | */ |
| | | @PutMapping("editTechRoute") |
| | | @PutMapping("/editTechRoute") |
| | | @Operation(summary = "ä¿®æ¹å·¥èºè·¯çº¿") |
| | | public R edit(@RequestBody TechnologyRouting technologyRouting) { |
| | | return R.ok(technologyRoutingService.updateTechnologyRouting(technologyRouting)); |
| | |
| | | return R.ok(technologyRoutingService.removeTechnologyRouting(ids)); |
| | | } |
| | | |
| | | //TODO å¢å å·¥èºè·¯çº¿éä»¶ä¸ä¼ @éæµ·æ° |
| | | } |
| | |
| | | Wrappers.<TechnologyBomStructure>lambdaQuery() |
| | | .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId()) |
| | | .isNotNull(TechnologyBomStructure::getOperationId) |
| | | .orderByAsc(TechnologyBomStructure::getId) |
| | | .orderByDesc(TechnologyBomStructure::getId) |
| | | ); |
| | | if (bomStructures.isEmpty()) { |
| | | throw new ServiceException("bom产åç»æä¸ºç©ºï¼"); |
| | | } |
| | | |
| | | // åä¸ä¸ª BOM ä¸å¯è½éå¤å¼ç¨ç¸åå·¥åºï¼è¿éæé¦æ¬¡åºç°é¡ºåºå»éã |
| | | // åä¸ä¸ª BOM ä¸å¯è½éå¤å¼ç¨ç¸åå·¥åºï¼æç
§ä¸ä¸å±çç¶èç¹çäº§åæ¯å¦ç¸ååå·¥åºæ¯å¦ç¸å |
| | | Map<Long, TechnologyBomStructure> structureById = new HashMap<>(); |
| | | for (TechnologyBomStructure bomStructure : bomStructures) { |
| | | if (bomStructure != null && bomStructure.getId() != null) { |
| | |
| | | |
| | | # æä»¶ä¸ä¼ é
ç½® |
| | | file: |
| | | temp-dir: D:/ruoyi/temp/uploads # 临æ¶ç®å½ |
| | | upload-dir: D:/ruoyi/prod/uploads # æ£å¼ç®å½ |
| | | temp-dir: D:/ruoyi/temp/uploads # 临æ¶ç®å½ åæå é¤ |
| | | upload-dir: D:/ruoyi/prod/uploads # æ£å¼ç®å½ åæå é¤ |
| | | path: C:/Users/12631/Desktop/download/uploads # ä¸ä¼ ç®å½ |
| | | urlPrefix: /common # 龿¥åç¼ |
| | | domain: http://127.0.0.1:7003 # åååç¼ |
| | |
| | | <result column="deleted" property="deleted" /> |
| | | <result column="record_type" property="recordType" /> |
| | | <result column="record_id" property="recordId" /> |
| | | <result column="name" property="name" /> |
| | | <result column="application" property="application" /> |
| | | <result column="storage_blob_id" property="storageBlobId" /> |
| | | </resultMap> |
| | | |
| | | <!-- éç¨æ¥è¯¢ç»æå --> |
| | | <sql id="Base_Column_List"> |
| | | id, create_time, update_time, deleted, record_type, record_id, name, storage_blob_id |
| | | </sql> |
| | | |
| | | </mapper> |
| | |
| | | <!-- éç¨æ¥è¯¢æ å°ç»æ --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StorageBlob"> |
| | | <id column="id" property="id" /> |
| | | <result column="create_time" property="createTime" /> |
| | | <result column="key" property="key" /> |
| | | <result column="resource_key" property="resourceKey"/> |
| | | <result column="content_type" property="contentType" /> |
| | | <result column="original_filename" property="originalFilename" /> |
| | | <result column="bucket_filename" property="bucketFilename" /> |
| | | <result column="bucket_name" property="bucketName" /> |
| | | <result column="uid_filename" property="uidFilename"/> |
| | | <result column="byte_size" property="byteSize" /> |
| | | <result column="path" property="path"/> |
| | | </resultMap> |
| | | |
| | | <!-- éç¨æ¥è¯¢ç»æå --> |
| | | <sql id="Base_Column_List"> |
| | | id, create_time, key, content_type, original_filename,bucket_filename,bucket_name, byte_size |
| | | id, resource_key, content_type, original_filename, uid_filename, byte_size, path |
| | | </sql> |
| | | |
| | | <select id="selectOrphanBlobsByIdRange" resultMap="BaseResultMap"> |
| | | SELECT |
| | | <include refid="Base_Column_List"/> |
| | | FROM storage_blob sb |
| | | LEFT JOIN storage_attachment sa |
| | | ON sa.storage_blob_id = sb.id |
| | | AND sa.deleted = 0 |
| | | WHERE sb.id <![CDATA[>]]> #{lastId} |
| | | AND sa.id IS NULL |
| | | ORDER BY sb.id ASC |
| | | LIMIT #{limit} |
| | | </select> |
| | | |
| | | <delete id="deleteByIdList"> |
| | | DELETE FROM storage_blob |
| | | WHERE id IN |
| | | <foreach collection="ids" item="id" open="(" separator="," close=")"> |
| | | #{id} |
| | | </foreach> |
| | | </delete> |
| | | |
| | | <select id="selectExistingUidFilenames" resultType="java.lang.String"> |
| | | SELECT uid_filename |
| | | FROM storage_blob |
| | | WHERE uid_filename IN |
| | | <foreach collection="fileNames" item="fileName" open="(" separator="," close=")"> |
| | | #{fileName} |
| | | </foreach> |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | <result column="dept_id" property="deptId" /> |
| | | </resultMap> |
| | | |
| | | <select id="listPage" resultType="com.ruoyi.production.bean.vo.ProductionAccountVo"> |
| | | select |
| | | group_concat(distinct p_parent.product_name order by p_parent.product_name separator ',') as productCategory, |
| | | group_concat(distinct pm.model order by pm.model separator ',') as specificationModel, |
| | | group_concat(distinct pm.unit order by pm.unit separator ',') as unit, |
| | | pa.scheduling_user_id as schedulingUserId, |
| | | pa.scheduling_user_name as schedulingUserName, |
| | | cast(sum( |
| | | ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$' |
| | | then cast(substring_index(pm.model, '*', -1) as decimal(18,4)) |
| | | else 1 |
| | | end |
| | | ) as decimal(18,4)) as wages, |
| | | cast(sum(ifnull(pa.finished_num, 0)) as decimal(18,4)) as finishedNum, |
| | | cast(sum(ifnull(pa.work_hours, 0)) as decimal(18,4)) as workHours, |
| | | case |
| | | when sum(ifnull(ppo.quantity, 0) + ifnull(ppo.scrapQty, 0)) = 0 then '0%' |
| | | else concat( |
| | | cast( |
| | | round( |
| | | sum(ifnull(ppo.quantity, 0)) / |
| | | sum(ifnull(ppo.quantity, 0) + ifnull(ppo.scrapQty, 0)) * 100, 2 |
| | | ) as char |
| | | ), |
| | | '%' |
| | | ) |
| | | end as outputRate, |
| | | group_concat(distinct pa.technology_operation_name order by pa.technology_operation_name separator ',') as process, |
| | | case |
| | | when count(distinct date(pa.scheduling_date)) = 1 then min(date(pa.scheduling_date)) |
| | | else null |
| | | end as schedulingDate, |
| | | case |
| | | when count(distinct date_format(pa.scheduling_date, '%Y-%m')) = 1 then min(date_format(pa.scheduling_date, '%Y-%m')) |
| | | else null |
| | | end as schedulingMonth |
| | | from production_account pa |
| | | left join production_product_main ppm on ppm.id = pa.production_product_main_id |
| | | left join production_operation_task pot on ppm.production_operation_task_id = pot.id |
| | | left join production_order po on pot.production_order_id = po.id |
| | | left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id |
| | | left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id) |
| | | left join product p on pm.product_id = p.id |
| | | left join product p_parent on p_parent.id = p.parent_id |
| | | left join ( |
| | | select production_product_main_id, |
| | | cast(sum(ifnull(quantity, 0)) as decimal(18,4)) as quantity, |
| | | cast(sum(ifnull(scrap_qty, 0)) as decimal(18,4)) as scrapQty |
| | | from production_product_output |
| | | group by production_product_main_id |
| | | ) ppo on ppo.production_product_main_id = ppm.id |
| | | <where> |
| | | <if test="c != null"> |
| | | <if test="c.productCategory != null and c.productCategory != ''"> |
| | | and p_parent.product_name like concat('%', #{c.productCategory}, '%') |
| | | </if> |
| | | <if test="c.specificationModel != null and c.specificationModel != ''"> |
| | | and pm.model like concat('%', #{c.specificationModel}, '%') |
| | | </if> |
| | | <if test="c.schedulingUserId != null"> |
| | | and pa.scheduling_user_id = #{c.schedulingUserId} |
| | | </if> |
| | | <if test="c.schedulingUserName != null and c.schedulingUserName != ''"> |
| | | and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%') |
| | | </if> |
| | | <if test="c.process != null and c.process != ''"> |
| | | and pa.technology_operation_name like concat('%', #{c.process}, '%') |
| | | </if> |
| | | <if test="c.entryDate != null"> |
| | | and date(pa.scheduling_date) = #{c.entryDate} |
| | | </if> |
| | | <if test="c.entryDateStart != null"> |
| | | and date(pa.scheduling_date) >= #{c.entryDateStart} |
| | | </if> |
| | | <if test="c.entryDateEnd != null"> |
| | | and date(pa.scheduling_date) <= #{c.entryDateEnd} |
| | | </if> |
| | | </if> |
| | | </where> |
| | | group by pa.scheduling_user_id, |
| | | pa.scheduling_user_name |
| | | order by wages desc, |
| | | pa.scheduling_user_id asc |
| | | </select> |
| | | |
| | | <select id="selectUserAccount" resultType="com.ruoyi.production.bean.dto.UserAccountDto"> |
| | | select ifnull(sum(finished_num), 0) as accountBalance, |
| | | ifnull(sum(work_hours), 0) as account |
| | |
| | | <select id="pageProductionOperationTask" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo"> |
| | | select pot.*, |
| | | po.nps_no as npsNo, |
| | | po.is_end_order as endOrder, |
| | | p.product_name as productName, |
| | | pm.model as model, |
| | | pm.unit as unit, |
| | |
| | | group by poro.technology_operation_id, poro.operation_name |
| | | </select> |
| | | |
| | | <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.bean.dto.ProductionOperationTaskDto"> |
| | | SELECT pot.*, |
| | | poro.operation_name AS processName, |
| | | pm.model AS model, |
| | | pm.unit AS unit, |
| | | p.product_name AS productName, |
| | | po.nps_no AS productOrderNpsNo, |
| | | ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus, |
| | | IFNULL(scrapStat.scrapQty, 0) AS scrapQty |
| | | FROM production_operation_task pot |
| | | LEFT JOIN production_order po ON pot.production_order_id = po.id |
| | | LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id |
| | | LEFT JOIN product_model pm ON pm.id = ifnull(poro.product_model_id, po.product_model_id) |
| | | LEFT JOIN product p ON p.id = pm.product_id |
| | | LEFT JOIN ( |
| | | SELECT ppm.production_operation_task_id AS taskId, |
| | | SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty |
| | | FROM production_product_main ppm |
| | | LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id |
| | | GROUP BY ppm.production_operation_task_id |
| | | ) scrapStat ON scrapStat.taskId = pot.id |
| | | WHERE pot.id = #{id} |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | po_sales.customerName, |
| | | p.product_name as productName, |
| | | pm.model as model, |
| | | po.is_end_order as endOrder, |
| | | tr.process_route_code as processRouteCode, |
| | | ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus, |
| | | tb.bom_no as bomNo |
| | | </sql> |
| | | |
| | |
| | | p.product_name as productName, |
| | | pm.model as productModelName, |
| | | pm.unit, |
| | | poro.operation_name as process, |
| | | pa.technology_operation_name as process, |
| | | ifnull(ppo.quantity, 0) as quantity, |
| | | ifnull(ppo.scrap_qty, 0) as scrapQty |
| | | from production_product_main ppm |
| | | ifnull(ppo.scrap_qty, 0) as scrapQty, |
| | | date(pa.scheduling_date) as schedulingDate, |
| | | pa.scheduling_user_name as schedulingUserName, |
| | | cast(ifnull(pa.work_hours, 0) as decimal(18,4)) as workHours, |
| | | cast( |
| | | ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$' |
| | | then cast(substring_index(pm.model, '*', -1) as decimal(18,4)) |
| | | else 1 |
| | | end |
| | | as decimal(18,4) |
| | | ) as wages |
| | | from production_account pa |
| | | left join production_product_main ppm on ppm.id = pa.production_product_main_id |
| | | left join production_operation_task pot on ppm.production_operation_task_id = pot.id |
| | | left join production_order po on pot.production_order_id = po.id |
| | | left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id |
| | | left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id) |
| | | left join product p on pm.product_id = p.id |
| | | left join product p_parent on p_parent.id = p.parent_id |
| | | left join production_product_output ppo on ppo.production_product_main_id = ppm.id |
| | | order by ppm.create_time desc |
| | | <where> |
| | | <if test="c != null"> |
| | | <if test="c.productCategory != null and c.productCategory != ''"> |
| | | and p_parent.product_name like concat('%', #{c.productCategory}, '%') |
| | | </if> |
| | | <if test="c.specificationModel != null and c.specificationModel != ''"> |
| | | and pm.model like concat('%', #{c.specificationModel}, '%') |
| | | </if> |
| | | <if test="c.schedulingUserId != null"> |
| | | and pa.scheduling_user_id = #{c.schedulingUserId} |
| | | </if> |
| | | <if test="c.schedulingUserName != null and c.schedulingUserName != ''"> |
| | | and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%') |
| | | </if> |
| | | <if test="c.process != null and c.process != ''"> |
| | | and pa.technology_operation_name like concat('%', #{c.process}, '%') |
| | | </if> |
| | | <if test="c.entryDate != null"> |
| | | and date(pa.scheduling_date) = #{c.entryDate} |
| | | </if> |
| | | <if test="c.entryDateStart != null"> |
| | | and date(pa.scheduling_date) >= #{c.entryDateStart} |
| | | </if> |
| | | <if test="c.entryDateEnd != null"> |
| | | and date(pa.scheduling_date) <= #{c.entryDateEnd} |
| | | </if> |
| | | </if> |
| | | </where> |
| | | order by pa.scheduling_date desc, pa.id desc |
| | | </select> |
| | | |
| | | <select id="listMain" resultType="java.lang.Long"> |
| | |
| | | </select> |
| | | <select id="selectUserByIds" resultType="com.ruoyi.project.system.domain.SysUser"> |
| | | <include refid="selectUserVo"/> |
| | | where u.user_id in <foreach collection="userIds" item="item" open="(" separator="," close=")"> |
| | | <where> |
| | | <if test="userIds != null and userIds.size > 0"> |
| | | and u.user_id in |
| | | <foreach collection="userIds" item="item" open="(" separator="," close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | and u.del_flag = '0' |
| | | </where> |
| | | </select> |
| | | <select id="selectRegistrantIds" resultType="com.ruoyi.project.system.domain.SysUser"> |
| | | SELECT user_id, nick_name FROM sys_user |