feat(aftersales): 新增售后模块数据权限管理和维修退货功能
- 添加AfterSaleNoRedisDAO实现售后单号生成功能
- 实现售后模块数据权限相关实体类、Mapper、Service及权限级别枚举
- 集成权限校验工具类AfterSalePermissionUtils支持多场景权限控制
- 开发售后维修记录的完整CRUD功能包括维修创建、更新、完成等操作
- 实现售后退货申请管理包括分页查询、审核、详情获取等功能
- 添加退货明细行数据对象及相应的映射处理
- 集成CRM客户信息展示退货申请中的客户名称
- 实现基于角色和权限的数据访问控制机制
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å®å工忍¡å - å端èè°æ¹æ¡ |
| | | |
| | | ## æ¶å页é¢ï¼å
¨é¨æ°å»ºï¼ |
| | | |
| | | | é¡µé¢ | è·¯ç±å»ºè®® | 说æ | |
| | | |------|---------|------| |
| | | | å®åå·¥åå表 | `/aftersales/ticket` | å·¥åå表ãæç´¢ãç¶æçé | |
| | | | å®åå·¥å详æ
/ç¼è¾ | `/aftersales/ticket/detail?id=:id` | æ°å»º/ç¼è¾å·¥åãæ¥ç详æ
| |
| | | | éè´§ç³è¯·å表 | `/aftersales/return` | éè´§ç³è¯·å表ãæç´¢ | |
| | | | éè´§ç³è¯·è¯¦æ
| `/aftersales/return/detail?id=:id` | é货详æ
ãå®¡æ ¸æä½ | |
| | | |
| | | ## ä¸å¡æµç¨ä¸æ°æ®å¸¦å
¥ |
| | | |
| | | ### æµç¨ä¸ï¼ä¸è¬é®é¢å·¥å |
| | | |
| | | ``` |
| | | å建工å â åé
å¤ç人 â é®é¢å¤å®ï¼ä¸è¬é®é¢ï¼â å¤ç â å®ç» â å
³é |
| | | ``` |
| | | |
| | | ### æµç¨äºï¼éè´§é®é¢å·¥å |
| | | |
| | | ``` |
| | | å建工å â åé
å¤ç人 â é®é¢å¤å®ï¼éè´§é®é¢ï¼ |
| | | â å建éè´§ç³è¯· â éå®å®¡æ ¸ â [MESéè´§æµç¨èªå¨æ§è¡] â 鿬¾/æ¢è´§å®æ â å®ç» â å
³é |
| | | ``` |
| | | |
| | | ### æµç¨ä¸ï¼ç»´ä¿®é®é¢å·¥å |
| | | |
| | | ``` |
| | | å建工å â åé
å¤ç人 â é®é¢å¤å®ï¼ç»´ä¿®é®é¢ï¼ |
| | | â åå»ºç»´ä¿®è®°å½ â ç»´ä¿®å®æ â å®ç» â å
³é |
| | | ``` |
| | | |
| | | ### æ°æ®å¸¦å
¥å
³ç³» |
| | | |
| | | | æ¥éª¤ | æ¥æº | 带å
¥å段 | |
| | | |------|------|----------| |
| | | | å建éè´§ç³è¯· | å·¥å详æ
| `ticketId`ã`customerId`ã`saleOrderId`ãå·¥åæç»è¡ï¼`ticketItemId`ã`itemId`ã`itemCode`ã`itemName`ï¼ | |
| | | | éè´§ç³è¯·å®¡æ¹ | éè´§ç³è¯· | `id`ï¼éè¿ URL åæ°ææé®ä¼ å
¥ï¼ | |
| | | |
| | | **éç¹è¯´æï¼** |
| | | - å建éè´§ç³è¯·æ¶ï¼ä»å·¥å详æ
页çæç»è¡ä¸çé `needReturn = true` çè¡ä½ä¸ºéè´§æç» |
| | | - éè´§æç»ä¸ç `ticketItemId` å¿
须对åºå·¥åæç»è¡ç `id` |
| | | - ç©æä¿¡æ¯ï¼`itemId`ã`itemCode`ã`itemName`ï¼ä»å·¥åæç»è¡å¸¦å
¥ï¼ä¸å
è®¸ä¿®æ¹ |
| | | - éå®åä»·ï¼`unitPrice`ï¼éè¦ä»éå®è®¢åè¡æ¥è¯¢è·åï¼å端å¯éè¿å·²æç ERP éå®è®¢åæ¥å£æ¥è¯¢ |
| | | |
| | | --- |
| | | |
| | | ## API 说æ |
| | | |
| | | ### ä¸ãå®åå·¥å |
| | | |
| | | | æ¹æ³ | è·¯å¾ | æé | 说æ | |
| | | |------|------|------|------| |
| | | | POST | `/aftersales/ticket/create` | `aftersales:ticket:create` | å建工å | |
| | | | PUT | `/aftersales/ticket/update` | `aftersales:ticket:update` | æ´æ°å·¥åï¼ä»
èç¨¿ç¶æå¯æ´æ°ï¼ | |
| | | | DELETE | `/aftersales/ticket/delete` | `aftersales:ticket:delete` | å é¤å·¥åï¼ä»
è稿/å·²åæ¶ç¶æå¯å é¤ï¼ | |
| | | | GET | `/aftersales/ticket/get` | `aftersales:ticket:query` | è·åå·¥å详æ
| |
| | | | GET | `/aftersales/ticket/page` | `aftersales:ticket:query` | å页æ¥è¯¢å·¥å | |
| | | | POST | `/aftersales/ticket/assign` | `aftersales:ticket:update` | åé
å¤ç人 | |
| | | | POST | `/aftersales/ticket/classify` | `aftersales:ticket:update` | é®é¢å¤å® | |
| | | | PUT | `/aftersales/ticket/resolve` | `aftersales:ticket:update` | å®ç»å·¥å | |
| | | | PUT | `/aftersales/ticket/close` | `aftersales:ticket:update` | å
³éå·¥å | |
| | | | PUT | `/aftersales/ticket/cancel` | `aftersales:ticket:update` | åæ¶å·¥å | |
| | | |
| | | #### 1.1 å建工å `POST /aftersales/ticket/create` |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | name | String | æ¯ | å·¥åä¸»é¢ | |
| | | | customerId | Long | æ¯ | 客æ·ç¼å· | |
| | | | contactId | Long | å¦ | è系人ç¼å· | |
| | | | saleOrderId | Long | å¦ | éå®è®¢åç¼å· | |
| | | | saleOrderNo | String | å¦ | éå®è®¢åå·ï¼åä½ï¼ä¸ saleOrderId é
å¥ä¼ å
¥ï¼ | |
| | | | contractId | Long | å¦ | ååç¼å· | |
| | | | issueDescription | String | å¦ | é®é¢æè¿° | |
| | | | remark | String | å¦ | 夿³¨ | |
| | | | items | List\<Item\> | å¦ | æç»è¡å表 | |
| | | |
| | | **Item ç»æï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | saleOrderItemId | Long | å¦ | éå®è®¢åè¡ç¼å· | |
| | | | itemId | Long | æ¯ | MDM ç©æç¼å· | |
| | | | itemCode | String | å¦ | ç©æç¼ç | |
| | | | itemName | String | å¦ | ç©æåç§° | |
| | | | batchId | Long | å¦ | çäº§æ¹æ¬¡ç¼å· | |
| | | | batchCode | String | å¦ | çäº§æ¹æ¬¡å· | |
| | | | saleQuantity | BigDecimal | å¦ | é宿°é | |
| | | | returnQuantity | BigDecimal | å¦ | éè´§æ°é | |
| | | | needRepair | Boolean | å¦ | æ¯å¦éè¦ç»´ä¿® | |
| | | | needReturn | Boolean | å¦ | æ¯å¦éè¦éè´§ | |
| | | | remark | String | å¦ | 夿³¨ | |
| | | |
| | | **请æ±ç¤ºä¾ï¼** |
| | | ```json |
| | | { |
| | | "name": "产åå¤è§ç¼ºé·æè¯", |
| | | "customerId": 1, |
| | | "contactId": 2, |
| | | "saleOrderId": 100, |
| | | "saleOrderNo": "SO202401010001", |
| | | "contractId": 50, |
| | | "issueDescription": "æ¶å°è´§ååç°äº§åè¡¨é¢æææ¾åç", |
| | | "remark": "客æ·è¦æ±å°½å¿«å¤ç", |
| | | "items": [ |
| | | { |
| | | "saleOrderItemId": 10, |
| | | "itemId": 200, |
| | | "itemCode": "MAT-001", |
| | | "itemName": "çµåå
å¨ä»¶", |
| | | "batchId": 5, |
| | | "batchCode": "BATCH-2024-001", |
| | | "saleQuantity": 100.000, |
| | | "returnQuantity": 10.000, |
| | | "needRepair": false, |
| | | "needReturn": true, |
| | | "remark": "å¤è§ç¼ºé·" |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | **ååºï¼** `{ "code": 0, "data": 1 }` â data 为æ°å»ºå·¥å ID |
| | | |
| | | #### 1.2 æ´æ°å·¥å `PUT /aftersales/ticket/update` |
| | | |
| | | 请æ±åæ°ä¸å建ç¸åï¼é¢å¤éè¦ `id` åæ®µãä»
èç¨¿ç¶æå¯æ´æ°ã |
| | | |
| | | #### 1.3 å é¤å·¥å `DELETE /aftersales/ticket/delete` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ååºï¼** `{ "code": 0, "data": true }` |
| | | |
| | | #### 1.4 è·åå·¥å详æ
`GET /aftersales/ticket/get` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ååºå段ï¼** |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | Long | å·¥åç¼å· | |
| | | | no | String | å·¥ååå·ï¼æ ¼å¼ï¼AS + yyyyMMdd + 6ä½åºå·ï¼ | |
| | | | name | String | å·¥åä¸»é¢ | |
| | | | customerId | Long | 客æ·ç¼å· | |
| | | | customerName | String | 客æ·åç§° | |
| | | | contactId | Long | è系人ç¼å· | |
| | | | contactName | String | è系人åç§° | |
| | | | saleOrderId | Long | éå®è®¢åç¼å· | |
| | | | saleOrderNo | String | éå®è®¢åå· | |
| | | | contractId | Long | ååç¼å· | |
| | | | issueType | Integer | é®é¢ç±»åï¼1-ä¸è¬é®é¢ 2-ç»´ä¿®é®é¢ 3-éè´§é®é¢ | |
| | | | issueCategory | String | é®é¢åç±» | |
| | | | issueDescription | String | é®é¢æè¿° | |
| | | | severityLevel | Integer | 严éç¨åº¦ï¼0-轻微 1-ä¸è¬ 2-严é 3-è´å½ | |
| | | | status | Integer | ç¶æï¼è§ç¶ææä¸¾ï¼ | |
| | | | ownerUserId | Long | è´è´£äººç¨æ·ç¼å· | |
| | | | ownerUserName | String | è´è´£äººåç§° | |
| | | | handlerUserId | Long | å¤çäººç¨æ·ç¼å· | |
| | | | handlerUserName | String | å¤ç人åç§° | |
| | | | processInstanceId | String | BPM 工使µå®ä¾ç¼å· | |
| | | | returnId | Long | å
³èéè´§ç³è¯·ç¼å· | |
| | | | repairId | Long | å
³è维修记å½ç¼å· | |
| | | | resolvedTime | DateTime | è§£å³æ¶é´ | |
| | | | closedTime | DateTime | å
³éæ¶é´ | |
| | | | remark | String | 夿³¨ | |
| | | | creator | String | å建è
| |
| | | | createTime | DateTime | å建æ¶é´ | |
| | | | updater | String | æ´æ°è
| |
| | | | updateTime | DateTime | æ´æ°æ¶é´ | |
| | | | items | List\<Item\> | æç»è¡å表 | |
| | | |
| | | **ååºç¤ºä¾ï¼** |
| | | ```json |
| | | { |
| | | "code": 0, |
| | | "data": { |
| | | "id": 1, |
| | | "no": "AS20260730000001", |
| | | "name": "产åå¤è§ç¼ºé·æè¯", |
| | | "customerId": 1, |
| | | "customerName": "XXç§ææéå
¬å¸", |
| | | "contactId": 2, |
| | | "contactName": "å¼ ä¸", |
| | | "saleOrderId": 100, |
| | | "saleOrderNo": "SO202401010001", |
| | | "contractId": 50, |
| | | "issueType": 3, |
| | | "issueCategory": "å¤è§ç¼ºé·", |
| | | "issueDescription": "æ¶å°è´§ååç°äº§åè¡¨é¢æææ¾åç", |
| | | "severityLevel": 1, |
| | | "status": 30, |
| | | "ownerUserId": 1, |
| | | "ownerUserName": "管çå", |
| | | "handlerUserId": 2, |
| | | "handlerUserName": "å®åä¸å", |
| | | "returnId": 1, |
| | | "items": [ |
| | | { |
| | | "id": 1, |
| | | "ticketId": 1, |
| | | "saleOrderItemId": 10, |
| | | "itemId": 200, |
| | | "itemCode": "MAT-001", |
| | | "itemName": "çµåå
å¨ä»¶", |
| | | "batchId": 5, |
| | | "batchCode": "BATCH-2024-001", |
| | | "saleQuantity": 100.000, |
| | | "returnQuantity": 10.000, |
| | | "needRepair": false, |
| | | "needReturn": true |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | #### 1.5 å页æ¥è¯¢å·¥å `GET /aftersales/ticket/page` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | pageNo | Integer | å¦ | 页ç ï¼é»è®¤ 1 | |
| | | | pageSize | Integer | å¦ | æ¯é¡µå¤§å°ï¼é»è®¤ 10 | |
| | | | no | String | å¦ | å·¥ååå· | |
| | | | name | String | å¦ | å·¥åä¸»é¢ | |
| | | | customerId | Long | å¦ | 客æ·ç¼å· | |
| | | | saleOrderId | Long | å¦ | éå®è®¢åç¼å· | |
| | | | status | Integer | å¦ | å·¥åç¶æ | |
| | | | issueType | Integer | å¦ | é®é¢ç±»å | |
| | | | sceneType | Integer | å¦ | åºæ¯ç±»åï¼1-æè´è´£ç 2-æåä¸ç 3-ä¸å±è´è´£ç 4-å
¨é¨ | |
| | | |
| | | **ååºï¼** |
| | | ```json |
| | | { |
| | | "code": 0, |
| | | "data": { |
| | | "list": [ /* AfterSaleTicketRespVO æ°ç» */ ], |
| | | "total": 100 |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | **注æï¼** å页å表ååºä¸çæ¯æ¡è®°å½ç»æä¸è¯¦æ
æ¥å£ä¸è´ï¼å« `items` åå
³èåç§°åæ®µï¼ï¼ä½åè¡¨åºæ¯ä¸ `items` å¯ä¸ºç©ºã |
| | | |
| | | #### 1.6 åé
å¤ç人 `POST /aftersales/ticket/assign` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | | handlerUserId | Long | æ¯ | å¤çäººç¨æ·ç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ä¸å¡è§åï¼** ä»
è稿ãå¤çä¸ç¶æå¯åé
ãåé
åç¶æèªå¨å为"å¤çä¸"ã |
| | | |
| | | #### 1.7 é®é¢å¤å® `POST /aftersales/ticket/classify` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | | issueType | Integer | æ¯ | é®é¢ç±»åï¼1-ä¸è¬é®é¢ 2-ç»´ä¿®é®é¢ 3-éè´§é®é¢ | |
| | | | issueCategory | String | å¦ | é®é¢åç±»ï¼å¦"å¤è§ç¼ºé·"ã"åè½æ
é"çï¼ | |
| | | | severityLevel | Integer | å¦ | 严éç¨åº¦ï¼0-轻微 1-ä¸è¬ 2-严é 3-è´å½ | |
| | | |
| | | **ä¸å¡è§åï¼** ä»
å¤çä¸ç¶æå¯å¤å®ãå¤å®ä¸ºéè´§é®é¢åï¼åºå¼å¯¼ç¨æ·å建éè´§ç³è¯·ã |
| | | |
| | | #### 1.8 å®ç»å·¥å `PUT /aftersales/ticket/resolve` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ä¸å¡è§åï¼** ä»
å¤çä¸/å¾
éè´§/å¾
鿬¾ç¶æå¯å®ç»ã |
| | | |
| | | #### 1.9 å
³éå·¥å `PUT /aftersales/ticket/close` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ä¸å¡è§åï¼** ä»
å·²å®ç»ç¶æå¯å
³éã |
| | | |
| | | #### 1.10 åæ¶å·¥å `PUT /aftersales/ticket/cancel` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | å·¥åç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ä¸å¡è§åï¼** ä»
è稿ãå¤çä¸ç¶æå¯åæ¶ã |
| | | |
| | | --- |
| | | |
| | | ### äºãå®åéè´§ç³è¯· |
| | | |
| | | | æ¹æ³ | è·¯å¾ | æé | 说æ | |
| | | |------|------|------|------| |
| | | | POST | `/aftersales/return/create` | `aftersales:return:create` | å建éè´§ç³è¯· | |
| | | | PUT | `/aftersales/return/approve` | `aftersales:return:approve` | å®¡æ ¸éè¿ï¼è§¦å MES éè´§åï¼ | |
| | | | GET | `/aftersales/return/get` | `aftersales:return:query` | è·åé货详æ
| |
| | | | GET | `/aftersales/return/page` | `aftersales:return:query` | å页æ¥è¯¢éè´§ç³è¯· | |
| | | |
| | | #### 2.1 å建éè´§ç³è¯· `POST /aftersales/return/create` |
| | | |
| | | **请æ±åæ°ï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | ticketId | Long | æ¯ | å
³èå·¥åç¼å· | |
| | | | customerId | Long | æ¯ | 客æ·ç¼å·ï¼ä»å·¥å带å
¥ï¼ | |
| | | | saleOrderId | Long | å¦ | å
³èéå®è®¢åç¼å·ï¼ä»å·¥å带å
¥ï¼ | |
| | | | returnType | Integer | æ¯ | éè´§ç±»åï¼1-鿬¾éè´§ 2-æ¢è´§ 3-ä»
鿬¾ | |
| | | | returnReason | String | æ¯ | éè´§åå | |
| | | | defectCategory | String | å¦ | 缺é·åç±» | |
| | | | remark | String | å¦ | 夿³¨ | |
| | | | items | List\<Item\> | æ¯ | éè´§æç»è¡å表 | |
| | | |
| | | **Item ç»æï¼** |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | ticketItemId | Long | æ¯ | å·¥åæç»è¡ç¼å·ï¼å
³è after_sale_ticket_item.idï¼ | |
| | | | itemId | Long | æ¯ | MDM ç©æç¼å·ï¼ä»å·¥åæç»è¡å¸¦å
¥ï¼ | |
| | | | itemCode | String | å¦ | ç©æç¼ç | |
| | | | itemName | String | å¦ | ç©æåç§° | |
| | | | batchId | Long | å¦ | æ¹æ¬¡ç¼å· | |
| | | | batchCode | String | å¦ | æ¹æ¬¡å· | |
| | | | returnQuantity | BigDecimal | æ¯ | éè´§æ°é | |
| | | | unitPrice | BigDecimal | æ¯ | éå®åä»·ï¼éä»éå®è®¢åè¡æ¥è¯¢è·åï¼ | |
| | | | returnPrice | BigDecimal | å¦ | éè´§éé¢ï¼= returnQuantity à unitPriceï¼ | |
| | | | remark | String | å¦ | 夿³¨ | |
| | | |
| | | **请æ±ç¤ºä¾ï¼** |
| | | ```json |
| | | { |
| | | "ticketId": 1, |
| | | "customerId": 1, |
| | | "saleOrderId": 100, |
| | | "returnType": 1, |
| | | "returnReason": "产åå¤è§ç¼ºé·", |
| | | "defectCategory": "å¤è§ç¼ºé·", |
| | | "remark": "客æ·è¦æ±éè´§éæ¬¾", |
| | | "items": [ |
| | | { |
| | | "ticketItemId": 1, |
| | | "itemId": 200, |
| | | "itemCode": "MAT-001", |
| | | "itemName": "çµåå
å¨ä»¶", |
| | | "batchId": 5, |
| | | "batchCode": "BATCH-2024-001", |
| | | "returnQuantity": 10.000, |
| | | "unitPrice": 100.00, |
| | | "returnPrice": 1000.00 |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | **ååºï¼** `{ "code": 0, "data": 1 }` â data 为æ°å»ºéè´§ç³è¯· ID |
| | | |
| | | **ä¸å¡è§åï¼** |
| | | - å建éè´§ç³è¯·åï¼å
³èå·¥åç¶æèªå¨å为"å¾
éè´§(30)" |
| | | - `returnPrice` å端ä¼èªå¨è®¡ç®ï¼`returnQuantity à unitPrice` æ±åï¼ï¼å端å¯ä¸ä¼ |
| | | |
| | | #### 2.2 å®¡æ ¸éè¿ `PUT /aftersales/return/approve` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | éè´§ç³è¯·ç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ä¸å¡è§åï¼** |
| | | - ä»
èç¨¿ç¶æ(0)å¯å®¡æ ¸ |
| | | - å®¡æ ¸éè¿åï¼å端èªå¨è°ç¨ MES å建éå®éè´§åï¼ç¶æå为"å®¡æ ¸éè¿-已忥MES(20)" |
| | | - åç» MES éè´§æµç¨ï¼è´¨æ£âå
¥åºâ鿬¾ï¼ç±å端åè°èªå¨å®æï¼å端æ éæä½ |
| | | |
| | | #### 2.3 è·åé货详æ
`GET /aftersales/return/get` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | id | Long | æ¯ | éè´§ç³è¯·ç¼å·ï¼Query åæ°ï¼ | |
| | | |
| | | **ååºåæ®µï¼æ°å¢/éè¦å段ï¼ï¼** |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | id | Long | éè´§ç³è¯·ç¼å· | |
| | | | no | String | éè´§åå·ï¼æ ¼å¼ï¼RT + yyyyMMdd + 6ä½åºå·ï¼ | |
| | | | ticketId | Long | å
³èå·¥åç¼å· | |
| | | | customerId | Long | 客æ·ç¼å· | |
| | | | customerName | String | 客æ·åç§° | |
| | | | saleOrderId | Long | éå®è®¢åç¼å· | |
| | | | returnType | Integer | éè´§ç±»å | |
| | | | returnReason | String | éè´§åå | |
| | | | defectCategory | String | 缺é·åç±» | |
| | | | totalReturnPrice | BigDecimal | åºéæ»éé¢ | |
| | | | actualRefundPrice | BigDecimal | å®ééé¢ | |
| | | | status | Integer | ç¶æï¼è§éè´§ç¶ææä¸¾ï¼ | |
| | | | auditUserId | Long | å®¡æ ¸äºº | |
| | | | auditTime | DateTime | å®¡æ ¸æ¶é´ | |
| | | | mesReturnId | Long | MESéè´§åç¼å· | |
| | | | mesReturnCode | String | MESéè´§åå· | |
| | | | qualityResult | String | è´¨æ£ç»è®º | |
| | | | qualityReportUrl | String | è´¨æ£æ¥åéä»¶URL | |
| | | | returnInboundTime | DateTime | éè´§å
¥åºå®ææ¶é´ | |
| | | | refundTime | DateTime | 鿬¾å®ææ¶é´ | |
| | | | items | List\<Item\> | éè´§æç»è¡ | |
| | | |
| | | #### 2.4 å页æ¥è¯¢éè´§ç³è¯· `GET /aftersales/return/page` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | pageNo | Integer | å¦ | 页ç | |
| | | | pageSize | Integer | å¦ | æ¯é¡µå¤§å° | |
| | | | no | String | å¦ | éè´§åå· | |
| | | | ticketId | Long | å¦ | å
³èå·¥åç¼å· | |
| | | | customerId | Long | å¦ | 客æ·ç¼å· | |
| | | | status | Integer | å¦ | éè´§ç¶æ | |
| | | | sceneType | Integer | å¦ | åºæ¯ç±»å | |
| | | |
| | | --- |
| | | |
| | | ## æä¸¾å¼éæ¥ |
| | | |
| | | ### å·¥åç¶æ (AfterSaleTicketStatusEnum) |
| | | |
| | | | å¼ | åç§° | 说æ | |
| | | |----|------|------| |
| | | | 0 | è稿 | å¯ç¼è¾ãå¯å é¤ãå¯åæ¶ | |
| | | | 10 | å¤çä¸ | å¯åé
ãå¯å¤å®ãå¯åæ¶ | |
| | | | 30 | å¾
éè´§ | éè´§æµç¨è¿è¡ä¸ | |
| | | | 40 | å¾
鿬¾/æ¢è´§ | çå¾
鿬¾ææ¢è´§å®æ | |
| | | | 50 | å·²å®ç» | å¯å
³é | |
| | | | 60 | å·²å
³é | ç»æ | |
| | | | 99 | 已忶 | ç»æ | |
| | | |
| | | ### é®é¢ç±»å (AfterSaleIssueTypeEnum) |
| | | |
| | | | å¼ | åç§° | åç»æä½ | |
| | | |----|------|----------| |
| | | | 0 | æªå¤å® | åå»ºå·¥åæ¶çåå§å¼ | |
| | | | 1 | ä¸è¬é®é¢ | ç´æ¥å¤çâå®ç» | |
| | | | 2 | ç»´ä¿®é®é¢ | å建维修记å½âç»´ä¿®å®æâå®ç» | |
| | | | 3 | éè´§é®é¢ | å建éè´§ç³è¯·âå®¡æ ¸âMESéè´§âå®ç» | |
| | | |
| | | ### éè´§ç¶æ (AfterSaleReturnStatusEnum) |
| | | |
| | | | å¼ | åç§° | 说æ | |
| | | |----|------|------| |
| | | | 0 | è稿 | å¯å®¡æ ¸ | |
| | | | 10 | éå®å®¡æ ¸ä¸ | â | |
| | | | 20 | å®¡æ ¸éè¿-已忥MES | çå¾
MESå¤ç | |
| | | | 30 | æ£éªä¸ | MESè´¨æ£è¿è¡ä¸ | |
| | | | 40 | æ£éªå®æ | çå¾
å
¥åº | |
| | | | 50 | å·²å
¥åº | çå¾
鿬¾ | |
| | | | 60 | 鿬¾/æ¢è´§å®æ | â | |
| | | | 70 | å·²å
³é | ç»æ | |
| | | | 99 | 已忶 | ç»æ | |
| | | |
| | | ### éè´§ç±»å |
| | | |
| | | | å¼ | åç§° | |
| | | |----|------| |
| | | | 1 | 鿬¾éè´§ | |
| | | | 2 | æ¢è´§ | |
| | | | 3 | ä»
鿬¾ | |
| | | |
| | | ### 严éç¨åº¦ |
| | | |
| | | | å¼ | åç§° | 建议é¢è² | |
| | | |----|------|----------| |
| | | | 0 | 轻微 | ç»¿è² | |
| | | | 1 | ä¸è¬ | èè² | |
| | | | 2 | 严é | æ©è² | |
| | | | 3 | è´å½ | çº¢è² | |
| | | |
| | | ### åºæ¯ç±»å (sceneType) |
| | | |
| | | | å¼ | åç§° | 说æ | |
| | | |----|------|------| |
| | | | 1 | æè´è´£ç | å½åç¨æ·ä¸ºè´è´£äºº | |
| | | | 2 | æåä¸ç | å½åç¨æ·ä¸ºå¤ç人æè¢«ææ | |
| | | | 3 | ä¸å±è´è´£ç | ä¸å±ä¸ºè´è´£äºº | |
| | | | 4 | å
¨é¨ | 管çåæ¥çææ | |
| | | |
| | | --- |
| | | |
| | | ## åæ®µå±ç¤ºè§å |
| | | |
| | | ### å·¥åå表页 |
| | | |
| | | | åæ®µ | å±ç¤ºä½ç½® | 说æ | |
| | | |------|----------|------| |
| | | | no | å表 | åå·ï¼å¯ç¹å»è¿å
¥è¯¦æ
| |
| | | | name | å表 | å·¥åä¸»é¢ | |
| | | | customerName | å表 | 客æ·åç§° | |
| | | | saleOrderNo | å表 | éå®è®¢åå· | |
| | | | issueType | å表 | é®é¢ç±»åï¼ç¨æ ç¾åºåé¢è² | |
| | | | severityLevel | å表 | 严éç¨åº¦ï¼ç¨æ ç¾åºåé¢è² | |
| | | | status | å表 | ç¶æï¼ç¨æ ç¾åºåé¢è² | |
| | | | ownerUserName | å表 | è´è´£äºº | |
| | | | handlerUserName | å表 | å¤ç人 | |
| | | | createTime | å表 | å建æ¶é´ | |
| | | | â | æç´¢åº | åå·ã主é¢ã客æ·ã订åãç¶æãé®é¢ç±»å | |
| | | | â | æç´¢åº | åºæ¯ç±»å Tabï¼æè´è´£ç/æåä¸ç/ä¸å±è´è´£ç/å
¨é¨ | |
| | | |
| | | ### å·¥å详æ
页 |
| | | |
| | | | åæ®µ | å±ç¤ºåºå | 说æ | |
| | | |------|----------|------| |
| | | | no | å¤´é¨ | åå· | |
| | | | name | å¤´é¨ | å·¥åä¸»é¢ | |
| | | | status | å¤´é¨ | ç¶ææ ç¾ + ç¶ææµè½¬æé® | |
| | | | customerId / customerName | åºæ¬ä¿¡æ¯ | 客æ·éæ©å¨ï¼å建æ¶å¯éï¼å建ååªè¯»ï¼ | |
| | | | contactId / contactName | åºæ¬ä¿¡æ¯ | èç³»äººéæ©å¨ | |
| | | | saleOrderId / saleOrderNo | åºæ¬ä¿¡æ¯ | éå®è®¢åéæ©å¨ | |
| | | | contractId | åºæ¬ä¿¡æ¯ | ååéæ©å¨ | |
| | | | issueType | åºæ¬ä¿¡æ¯ | é®é¢ç±»åï¼å¤å®åæ¾ç¤ºï¼ | |
| | | | issueCategory | åºæ¬ä¿¡æ¯ | é®é¢åç±»ï¼å¤å®åæ¾ç¤ºï¼ | |
| | | | issueDescription | åºæ¬ä¿¡æ¯ | é®é¢æè¿° | |
| | | | severityLevel | åºæ¬ä¿¡æ¯ | 严éç¨åº¦ï¼å¤å®åæ¾ç¤ºï¼ | |
| | | | ownerUserId / ownerUserName | åºæ¬ä¿¡æ¯ | è´è´£äººï¼å建æ¶èªå¨è®¾ä¸ºå½åç¨æ·ï¼ | |
| | | | handlerUserId / handlerUserName | åºæ¬ä¿¡æ¯ | å¤ç人ï¼åé
åæ¾ç¤ºï¼ | |
| | | | returnId | åºæ¬ä¿¡æ¯ | å
³èéè´§ç³è¯·ï¼å¯ç¹å»è·³è½¬ï¼ | |
| | | | repairId | åºæ¬ä¿¡æ¯ | å
³è维修记å½ï¼å¯ç¹å»è·³è½¬ï¼ | |
| | | | resolvedTime | åºæ¬ä¿¡æ¯ | è§£å³æ¶é´ï¼å®ç»åæ¾ç¤ºï¼ | |
| | | | closedTime | åºæ¬ä¿¡æ¯ | å
³éæ¶é´ï¼å
³éåæ¾ç¤ºï¼ | |
| | | | remark | åºæ¬ä¿¡æ¯ | 夿³¨ | |
| | | | items | æç»è¡¨æ ¼ | ç©æãæ¹æ¬¡ãé宿°éãéè´§æ°éãæ¯å¦ç»´ä¿®ãæ¯å¦éè´§ | |
| | | | createTime / creator | åºé¨ä¿¡æ¯ | åå»ºä¿¡æ¯ | |
| | | | updateTime / updater | åºé¨ä¿¡æ¯ | æ´æ°ä¿¡æ¯ | |
| | | |
| | | ### éè´§ç³è¯·å表页 |
| | | |
| | | | åæ®µ | å±ç¤ºä½ç½® | 说æ | |
| | | |------|----------|------| |
| | | | no | å表 | éè´§åå· | |
| | | | ticketId | å表 | å
³èå·¥åç¼å·ï¼å¯ç¹å»è·³è½¬ï¼ | |
| | | | customerName | å表 | 客æ·åç§° | |
| | | | returnType | å表 | éè´§ç±»åæ ç¾ | |
| | | | totalReturnPrice | å表 | åºéæ»éé¢ | |
| | | | actualRefundPrice | å表 | å®ééé¢ | |
| | | | status | å表 | ç¶ææ ç¾ | |
| | | | mesReturnCode | å表 | MESéè´§åå· | |
| | | | qualityResult | å表 | è´¨æ£ç»è®º | |
| | | | createTime | å表 | å建æ¶é´ | |
| | | |
| | | ### éè´§ç³è¯·è¯¦æ
页 |
| | | |
| | | | åæ®µ | å±ç¤ºåºå | 说æ | |
| | | |------|----------|------| |
| | | | no | å¤´é¨ | éè´§åå· | |
| | | | status | å¤´é¨ | ç¶ææ ç¾ + å®¡æ ¸æé®ï¼èç¨¿ç¶ææ¾ç¤ºï¼ | |
| | | | ticketId | åºæ¬ä¿¡æ¯ | å
³èå·¥åï¼å¯ç¹å»è·³è½¬ï¼ | |
| | | | customerName | åºæ¬ä¿¡æ¯ | 客æ·åç§° | |
| | | | saleOrderId | åºæ¬ä¿¡æ¯ | éå®è®¢å | |
| | | | returnType | åºæ¬ä¿¡æ¯ | éè´§ç±»å | |
| | | | returnReason | åºæ¬ä¿¡æ¯ | éè´§åå | |
| | | | defectCategory | åºæ¬ä¿¡æ¯ | 缺é·åç±» | |
| | | | totalReturnPrice | åºæ¬ä¿¡æ¯ | åºéæ»éé¢ | |
| | | | actualRefundPrice | åºæ¬ä¿¡æ¯ | å®ééé¢ | |
| | | | mesReturnId / mesReturnCode | MESä¿¡æ¯ | MESéè´§å | |
| | | | qualityResult | MESä¿¡æ¯ | è´¨æ£ç»è®º | |
| | | | qualityReportUrl | MESä¿¡æ¯ | è´¨æ£æ¥å龿¥ | |
| | | | returnInboundTime | MESä¿¡æ¯ | å
¥åºæ¶é´ | |
| | | | refundTime | 鿬¾ä¿¡æ¯ | 鿬¾æ¶é´ | |
| | | | items | æç»è¡¨æ ¼ | ç©æãæ¹æ¬¡ãéè´§æ°éãåä»·ãéè´§éé¢ | |
| | | | createTime / creator | åºé¨ä¿¡æ¯ | åå»ºä¿¡æ¯ | |
| | | |
| | | --- |
| | | |
| | | ## ä¸å¡è§å说æ |
| | | |
| | | ### å·¥åæä½æé®æ¾éè§å |
| | | |
| | | | æä½ | è稿(0) | å¤çä¸(10) | å¾
éè´§(30) | å¾
鿬¾(40) | å·²å®ç»(50) | å·²å
³é(60) | 已忶(99) | |
| | | |------|---------|------------|------------|------------|------------|------------|------------| |
| | | | ç¼è¾ | â
| â | â | â | â | â | â | |
| | | | å é¤ | â
| â | â | â | â | â | â
| |
| | | | åé
å¤ç人 | â
| â
| â | â | â | â | â | |
| | | | é®é¢å¤å® | â | â
| â | â | â | â | â | |
| | | | å建éè´§ç³è¯· | â | â
(å¤å®ä¸ºéè´§å) | â | â | â | â | â | |
| | | | å®ç» | â | â
| â
| â
| â | â | â | |
| | | | å
³é | â | â | â | â | â
| â | â | |
| | | | åæ¶ | â
| â
| â | â | â | â | â | |
| | | |
| | | ### éè´§ç³è¯·æä½æé®æ¾éè§å |
| | | |
| | | | æä½ | è稿(0) | å®¡æ ¸ä¸(10) | 已忥MES(20) | æ£éªä¸(30) | æ£éªå®æ(40) | å·²å
¥åº(50) | 鿬¾å®æ(60) | |
| | | |------|---------|------------|---------------|------------|--------------|------------|--------------| |
| | | | å®¡æ ¸éè¿ | â
| â | â | â | â | â | â | |
| | | | æ¥ç详æ
| â
| â
| â
| â
| â
| â
| â
| |
| | | |
| | | ### å页æ¥è¯¢æ°æ®æé说æ |
| | | |
| | | - **sceneType=1ï¼æè´è´£çï¼**ï¼æ¾ç¤ºå½åç¨æ·ä¸º `ownerUserId` çå·¥å + æ°æ®äº¤æ¥çå·¥å |
| | | - **sceneType=2ï¼æåä¸çï¼**ï¼æ¾ç¤ºå½åç¨æ·æè¯»/åæéçå·¥å |
| | | - **sceneType=3ï¼ä¸å±è´è´£çï¼**ï¼æ¾ç¤ºå½åç¨æ·çä¸å±è´è´£çå·¥å |
| | | - **sceneType=4ï¼å
¨é¨ï¼**ï¼éè¦ç®¡çåæéï¼`aftersales:admin`ï¼ |
| | | |
| | | --- |
| | | |
| | | ## æä»¶ä¸ä¼ |
| | | |
| | | å®å模å使ç¨ç»ä¸çæä»¶ä¸ä¼ æºå¶ï¼ä¸èªè¡å®ç°ä¸ä¼ æ¥å£ã |
| | | |
| | | **ä¸ä¼ æµç¨ï¼** |
| | | 1. è°ç¨ `POST /system/storage-blob/upload` ä¸ä¼ æä»¶ â è·å¾ `blobId` |
| | | 2. è°ç¨ `POST /system/storage-attachment/bind` ç»å®å°ä¸å¡è®°å½ |
| | | |
| | | **recordType åå¼ï¼** |
| | | |
| | | | ä¸å¡å¯¹è±¡ | recordType | |
| | | |----------|------------| |
| | | | å®åå·¥å | `aftersales_ticket` | |
| | | | å®åéè´§ç³è¯· | `aftersales_return` | |
| | | |
| | | **æ¥è¯¢éä»¶ï¼** `GET /system/storage-attachment/list?recordType=aftersales_ticket&recordId=1` |
| | | |
| | | --- |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | 1. **æç»è¡æ´æ°çç¥**ï¼æ´æ°å·¥åæ¶ï¼æç»è¡éç¨"å
å åå¢"çç¥ï¼å端å¿
é¡»ä¼ å
¥å®æ´çæç»è¡å表ï¼å
æ¬æªä¿®æ¹çè¡ï¼ï¼å¦åä¼å¯¼è´æç»è¡ä¸¢å¤±ã |
| | | 2. **åå·çæ**ï¼å·¥ååå·ï¼ASåç¼ï¼åéè´§åå·ï¼RTåç¼ï¼ç±å端èªå¨çæï¼å端ä¸éè¦ä¼ å
¥ã |
| | | 3. **ç¶ææµè½¬**ï¼ææç¶æåæ´æä½ï¼åé
ãå¤å®ãå®ç»ãå
³éãåæ¶ãå®¡æ ¸ï¼å端é½ä¼æ ¡éªå½åç¶ææ¯å¦å
许ï¼åç«¯åºæ ¹æ®æé®æ¾éè§åæ§å¶æä½å
¥å£ã |
| | | 4. **éè´§å®¡æ ¸åèªå¨åæ¥ MES**ï¼å®¡æ ¸éè¿éè´§ç³è¯·åï¼å端èªå¨è°ç¨ MES å建éå®éè´§åï¼åç» MES æµç¨ï¼è´¨æ£âå
¥åºâ鿬¾ï¼ç±åè°èªå¨æ¨è¿ç¶æï¼å端åªéè½®è¯¢å·æ°æ¥çææ°ç¶æã |
| | | 5. **æ°æ®å¸¦å
¥**ï¼å建éè´§ç³è¯·æ¶ï¼å¿
é¡»ä»å·¥å详æ
页跳转并带å
¥ `ticketId`ã`customerId`ã`saleOrderId` 以åå·¥åæç»è¡ä¸æ 记为"éè¦éè´§"çè¡ã |
| | | 6. **æéæ§å¶**ï¼æææ¥å£é½æ `@PreAuthorize` æéæ ¡éªï¼å端èååæé®éè¦å¯¹åºé
ç½®æéæ è¯ã |
| | | 7. **è·¯ç±æé**ï¼éå¨ `src/router/routes/modules/` 䏿°å»º `aftersales.ts` è·¯ç±æ¨¡åæä»¶ï¼å¹¶å¨èå䏿³¨å"å®åæå¡"ä¸çº§èåã |
| | | 8. **API 模å**ï¼éå¨ `src/api/` 䏿°å»º `aftersales/` ç®å½ï¼å建 `ticket.ts` å `return.ts` 两个 API æä»¶ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ============================================================ |
| | | -- å®å工忍¡å DDL |
| | | -- ============================================================ |
| | | |
| | | -- 1. å®åå·¥å主表 |
| | | DROP TABLE IF EXISTS `after_sale_ticket`; |
| | | CREATE TABLE `after_sale_ticket` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'å·¥åç¼å·', |
| | | `no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'å·¥ååå·', |
| | | `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'å·¥å主é¢/æ é¢', |
| | | `customer_id` bigint NOT NULL COMMENT '客æ·ç¼å·ï¼å
³è crm_customer.id', |
| | | `contact_id` bigint DEFAULT NULL COMMENT 'è系人ç¼å·ï¼å
³è crm_contact.id', |
| | | `sale_order_id` bigint DEFAULT NULL COMMENT 'éå®è®¢åç¼å·ï¼å
³è erp_sale_order.id', |
| | | `sale_order_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'éå®è®¢åå·(åä½)', |
| | | `contract_id` bigint DEFAULT NULL COMMENT 'ååç¼å·ï¼å
³è crm_contract.id', |
| | | `issue_type` tinyint NOT NULL DEFAULT 0 COMMENT 'é®é¢ç±»å: 0-æªå¤å® 1-ä¸è¬é®é¢ 2-ç»´ä¿®é®é¢ 3-éè´§é®é¢', |
| | | `issue_category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'é®é¢åç±»', |
| | | `issue_description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'é®é¢æè¿°', |
| | | `severity_level` tinyint DEFAULT 0 COMMENT '严éç¨åº¦: 0-轻微 1-ä¸è¬ 2-严é 3-è´å½', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æ: 0-è稿 10-å¤çä¸ 30-å¾
éè´§ 40-å¾
鿬¾/æ¢è´§ 50-å·²å®ç» 60-å·²å
³é 99-已忶', |
| | | `owner_user_id` bigint NOT NULL COMMENT 'è´è´£äººç¨æ·ç¼å·', |
| | | `handler_user_id` bigint DEFAULT NULL COMMENT 'å¤çäººç¨æ·ç¼å·', |
| | | `process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'BPM工使µå®ä¾ç¼å·', |
| | | `return_id` bigint DEFAULT NULL COMMENT 'å
³èéè´§ç³è¯·ç¼å·', |
| | | `repair_id` bigint DEFAULT NULL COMMENT 'å
³è维修记å½ç¼å·', |
| | | `resolved_time` datetime DEFAULT NULL COMMENT 'è§£å³æ¶é´', |
| | | `closed_time` datetime DEFAULT NULL COMMENT 'å
³éæ¶é´', |
| | | `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | UNIQUE KEY `uk_no` (`no`), |
| | | KEY `idx_customer_id` (`customer_id`), |
| | | KEY `idx_sale_order_id` (`sale_order_id`), |
| | | KEY `idx_owner_user_id` (`owner_user_id`), |
| | | KEY `idx_status` (`status`), |
| | | KEY `idx_create_time` (`create_time`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®åå·¥å主表'; |
| | | |
| | | -- 2. å®åå·¥åæç»è¡è¡¨ |
| | | DROP TABLE IF EXISTS `after_sale_ticket_item`; |
| | | CREATE TABLE `after_sale_ticket_item` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ç¼å·', |
| | | `ticket_id` bigint NOT NULL COMMENT 'å·¥åç¼å·ï¼å
³è after_sale_ticket.id', |
| | | `sale_order_item_id` bigint DEFAULT NULL COMMENT 'éå®è®¢åè¡ç¼å·', |
| | | `item_id` bigint NOT NULL COMMENT 'MDMç©æç¼å·', |
| | | `item_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ç©æç¼ç (åä½)', |
| | | `item_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ç©æåç§°(åä½)', |
| | | `batch_id` bigint DEFAULT NULL COMMENT 'çäº§æ¹æ¬¡ç¼å·', |
| | | `batch_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'çäº§æ¹æ¬¡å·', |
| | | `sale_quantity` decimal(10,3) NOT NULL DEFAULT 0.000 COMMENT 'é宿°é', |
| | | `return_quantity` decimal(10,3) DEFAULT 0.000 COMMENT 'éè´§æ°é', |
| | | `need_repair` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦éè¦ç»´ä¿®', |
| | | `need_return` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦éè¦éè´§', |
| | | `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | KEY `idx_ticket_id` (`ticket_id`), |
| | | KEY `idx_item_id` (`item_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®åå·¥åæç»è¡è¡¨'; |
| | | |
| | | -- 3. éè´§ç³è¯·è¡¨ |
| | | DROP TABLE IF EXISTS `after_sale_return`; |
| | | CREATE TABLE `after_sale_return` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'éè´§ç³è¯·ç¼å·', |
| | | `no` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'éè´§åå·', |
| | | `ticket_id` bigint NOT NULL COMMENT 'å
³èå·¥åç¼å·ï¼å
³è after_sale_ticket.id', |
| | | `customer_id` bigint NOT NULL COMMENT '客æ·ç¼å·', |
| | | `sale_order_id` bigint DEFAULT NULL COMMENT 'å
³èéå®è®¢åç¼å·', |
| | | `return_type` tinyint NOT NULL COMMENT 'éè´§ç±»å: 1-鿬¾éè´§ 2-æ¢è´§ 3-ä»
鿬¾', |
| | | `return_reason` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'éè´§åå ', |
| | | `defect_category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '缺é·åç±»', |
| | | `total_return_price` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT 'åºéæ»éé¢', |
| | | `actual_refund_price` decimal(12,2) DEFAULT 0.00 COMMENT 'å®ééé¢', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æ: 0-è稿 10-éå®å®¡æ ¸ä¸ 20-å®¡æ ¸éè¿å·²åæ¥MES 30-æ£éªä¸ 40-æ£éªå®æ 50-å·²å
¥åº 60-鿬¾/æ¢è´§å®æ 70-å·²å
³é 99-已忶', |
| | | `audit_user_id` bigint DEFAULT NULL COMMENT 'å®¡æ ¸äºº', |
| | | `audit_time` datetime DEFAULT NULL COMMENT 'å®¡æ ¸æ¶é´', |
| | | `mes_return_id` bigint DEFAULT NULL COMMENT 'MESéè´§åç¼å·ï¼å
³è mes_wm_return_sales.id', |
| | | `mes_return_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'MESéè´§åå·(åä½)', |
| | | `quality_result` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'è´¨æ£ç»è®º: åæ ¼/ç¹é/éè´§/æ¥åº', |
| | | `quality_report_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'è´¨æ£æ¥åéä»¶URL', |
| | | `return_inbound_time` datetime DEFAULT NULL COMMENT 'éè´§å
¥åºå®ææ¶é´', |
| | | `refund_time` datetime DEFAULT NULL COMMENT '鿬¾/æ¢è´§å®ææ¶é´', |
| | | `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | UNIQUE KEY `uk_no` (`no`), |
| | | KEY `idx_ticket_id` (`ticket_id`), |
| | | KEY `idx_mes_return_id` (`mes_return_id`), |
| | | KEY `idx_status` (`status`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®åéè´§ç³è¯·è¡¨'; |
| | | |
| | | -- 4. éè´§æç»è¡è¡¨ |
| | | DROP TABLE IF EXISTS `after_sale_return_item`; |
| | | CREATE TABLE `after_sale_return_item` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ç¼å·', |
| | | `return_id` bigint NOT NULL COMMENT 'éè´§ç³è¯·ç¼å·ï¼å
³è after_sale_return.id', |
| | | `ticket_item_id` bigint NOT NULL COMMENT 'å·¥åæç»è¡ç¼å·ï¼å
³è after_sale_ticket_item.id', |
| | | `item_id` bigint NOT NULL COMMENT 'MDMç©æç¼å·', |
| | | `item_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ç©æç¼ç (åä½)', |
| | | `item_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ç©æåç§°(åä½)', |
| | | `batch_id` bigint DEFAULT NULL COMMENT 'æ¹æ¬¡ç¼å·', |
| | | `batch_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'æ¹æ¬¡å·', |
| | | `return_quantity` decimal(10,3) NOT NULL COMMENT 'éè´§æ°é', |
| | | `unit_price` decimal(12,2) NOT NULL COMMENT 'éå®åä»·', |
| | | `return_price` decimal(12,2) NOT NULL COMMENT 'éè´§éé¢', |
| | | `mes_return_line_id` bigint DEFAULT NULL COMMENT 'MESéè´§åè¡ç¼å·', |
| | | `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | KEY `idx_return_id` (`return_id`), |
| | | KEY `idx_ticket_item_id` (`ticket_item_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®åéè´§æç»è¡è¡¨'; |
| | | |
| | | -- 5. 维修记å½è¡¨ |
| | | DROP TABLE IF EXISTS `after_sale_repair`; |
| | | CREATE TABLE `after_sale_repair` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '维修记å½ç¼å·', |
| | | `ticket_id` bigint NOT NULL COMMENT 'å
³èå·¥åç¼å·ï¼å
³è after_sale_ticket.id', |
| | | `repair_type` tinyint NOT NULL COMMENT '维修类å: 1-ç°åºç»´ä¿® 2-è¿åç»´ä¿® 3-è¿ç¨æå¯¼', |
| | | `fault_description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'æ
éæè¿°', |
| | | `repair_action` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT 'ç»´ä¿®æªæ½', |
| | | `repair_result` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'ç»´ä¿®ç»æ: 已修å¤/æ æ³ä¿®å¤/é¨åä¿®å¤', |
| | | `repair_cost` decimal(10,2) DEFAULT 0.00 COMMENT '维修费ç¨', |
| | | `repair_user_id` bigint DEFAULT NULL COMMENT '维修人', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æ: 0-å¾
å¤ç 10-ç»´ä¿®ä¸ 20-已宿 30-å·²å
³é', |
| | | `start_time` datetime DEFAULT NULL COMMENT 'å¼å§ç»´ä¿®æ¶é´', |
| | | `finish_time` datetime DEFAULT NULL COMMENT 'å®æç»´ä¿®æ¶é´', |
| | | `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | KEY `idx_ticket_id` (`ticket_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®å维修记å½è¡¨'; |
| | | |
| | | -- 6. å®åæ°æ®æé表 |
| | | DROP TABLE IF EXISTS `after_sale_permission`; |
| | | CREATE TABLE `after_sale_permission` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ç¼å·', |
| | | `biz_type` tinyint NOT NULL COMMENT 'æ°æ®ç±»å: 1-å®åå·¥å 2-éè´§ç³è¯· 3-维修记å½', |
| | | `biz_id` bigint NOT NULL COMMENT 'æ°æ®ç¼å·', |
| | | `user_id` bigint NOT NULL COMMENT 'ç¨æ·ç¼å·', |
| | | `level` tinyint NOT NULL COMMENT 'æé级å«: 1-è´è´£äºº 2-åªè¯» 3-读å', |
| | | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT 'æ´æ°è
', |
| | | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´', |
| | | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤', |
| | | PRIMARY KEY (`id`) USING BTREE, |
| | | KEY `idx_biz` (`biz_type`, `biz_id`), |
| | | KEY `idx_user` (`user_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='å®åæ°æ®æé表'; |
| | |
| | | <!-- SRM ä¾åºåå
³ç³»ç®¡ç模å --> |
| | | <module>yudao-module-srm-api</module> |
| | | <module>yudao-module-srm</module> |
| | | <!-- å®å工忍¡å --> |
| | | <module>yudao-module-aftersales-api</module> |
| | | <module>yudao-module-aftersales</module> |
| | | <!-- 请åè https://doc.iocoder.cn/ai/build/ ææ¡£ï¼å®æ AI 模åçå¯å¨ï¼ï¼ï¼ --> |
| | | <!-- <module>yudao-module-ai</module>--> |
| | | </modules> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <artifactId>yudao-module-aftersales-api</artifactId> |
| | | <packaging>jar</packaging> |
| | | |
| | | <name>${project.artifactId}</name> |
| | | <description> |
| | | å®å工忍¡åç API æ¥å£å®ä¹ï¼ä¾å
¶ä»æ¨¡åå¼ç¨ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-common</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- Swagger 注解 --> |
| | | <dependency> |
| | | <groupId>org.springdoc</groupId> |
| | | <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.api; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.module.aftersales.api.dto.AfterSaleReturnRespDTO; |
| | | import cn.iocoder.yudao.module.aftersales.api.dto.AfterSaleTicketRespDTO; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * å®åå·¥å API æ¥å£ï¼ä¾ MES/ERP 跨模åè°ç¨ï¼ |
| | | */ |
| | | public interface AfterSaleTicketApi { |
| | | |
| | | String PREFIX = "/rpc-api/aftersales/ticket"; |
| | | |
| | | /** |
| | | * MES éè´§è´¨æ£å®æååè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | * @param qualityResult è´¨æ£ç»è®º |
| | | * @param reportUrl è´¨æ£æ¥å URL |
| | | */ |
| | | CommonResult<Boolean> onReturnQualityFinished(Long returnId, String qualityResult, String reportUrl); |
| | | |
| | | /** |
| | | * MES éè´§å
¥åºå®æååè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | */ |
| | | CommonResult<Boolean> onReturnInboundFinished(Long returnId); |
| | | |
| | | /** |
| | | * ERP 鿬¾å®æååè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | * @param actualRefundPrice å®ééé¢ |
| | | */ |
| | | CommonResult<Boolean> onRefundCompleted(Long returnId, BigDecimal actualRefundPrice); |
| | | |
| | | /** |
| | | * æ¥è¯¢å®åå·¥åï¼ä¾ MES/ERP æ¥è¯¢å
³èä¿¡æ¯ï¼ |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | */ |
| | | CommonResult<AfterSaleTicketRespDTO> getTicket(Long id); |
| | | |
| | | /** |
| | | * æ¥è¯¢éè´§ç³è¯·ï¼ä¾ MES/ERP æ¥è¯¢å
³èä¿¡æ¯ï¼ |
| | | * |
| | | * @param id éè´§ç³è¯·ç¼å· |
| | | */ |
| | | CommonResult<AfterSaleReturnRespDTO> getReturn(Long id); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.api.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯·ååº DTOï¼ä¾ RPC è°ç¨ä½¿ç¨ï¼ |
| | | */ |
| | | @Data |
| | | public class AfterSaleReturnRespDTO { |
| | | |
| | | private Long id; |
| | | private String no; |
| | | private Long ticketId; |
| | | private Long customerId; |
| | | private Long saleOrderId; |
| | | private Integer returnType; |
| | | private String returnReason; |
| | | private BigDecimal totalReturnPrice; |
| | | private BigDecimal actualRefundPrice; |
| | | private Integer status; |
| | | private Long mesReturnId; |
| | | private String mesReturnCode; |
| | | private String qualityResult; |
| | | private String qualityReportUrl; |
| | | private LocalDateTime returnInboundTime; |
| | | private LocalDateTime refundTime; |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.api.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®åå·¥åååº DTOï¼ä¾ RPC è°ç¨ä½¿ç¨ï¼ |
| | | */ |
| | | @Data |
| | | public class AfterSaleTicketRespDTO { |
| | | |
| | | private Long id; |
| | | private String no; |
| | | private String name; |
| | | private Long customerId; |
| | | private Long saleOrderId; |
| | | private String saleOrderNo; |
| | | private Integer issueType; |
| | | private String issueCategory; |
| | | private String issueDescription; |
| | | private Integer severityLevel; |
| | | private Integer status; |
| | | private Long ownerUserId; |
| | | private Long handlerUserId; |
| | | private Long returnId; |
| | | private Long repairId; |
| | | private LocalDateTime resolvedTime; |
| | | private LocalDateTime createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <artifactId>yudao-module-aftersales</artifactId> |
| | | <packaging>jar</packaging> |
| | | |
| | | <name>${project.artifactId}</name> |
| | | <description> |
| | | aftersales å
ä¸ï¼å®åæå¡ç®¡çï¼After-sales Service Managementï¼ã |
| | | ä¾å¦è¯´ï¼å®åå·¥åãéè´§ç³è¯·ã维修记å½çç |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- å®å API 模å --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-aftersales-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- CRM API 模å --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-crm-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-system</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-infra</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-bpm</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- MDM ä¸»æ°æ®ç®¡ç API --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-mdm-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ERP éå®è®¢å API --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-erp-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- MES API --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-mes-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- HRM APIï¼æ°æ®äº¤æ¥ï¼ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-hrm-api</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ä¸å¡ç»ä»¶ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- Web ç¸å
³ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-web</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-security</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- DB ç¸å
³ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-mybatis</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- å·¥å
·ç±»ç¸å
³ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-excel</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- Test æµè¯ç¸å
³ --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-spring-boot-starter-test</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.api; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.api.dto.AfterSaleReturnRespDTO; |
| | | import cn.iocoder.yudao.module.aftersales.api.dto.AfterSaleTicketRespDTO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.service.returnobj.AfterSaleReturnService; |
| | | import cn.iocoder.yudao.module.aftersales.service.ticket.AfterSaleTicketService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | |
| | | /** |
| | | * å®åå·¥å API å®ç°ç±»ï¼ä¾ MES/ERP 跨模åè°ç¨ï¼ |
| | | */ |
| | | @RestController |
| | | public class AfterSaleTicketApiImpl implements AfterSaleTicketApi { |
| | | |
| | | @Resource |
| | | private AfterSaleTicketService ticketService; |
| | | @Resource |
| | | private AfterSaleReturnService returnService; |
| | | |
| | | @Override |
| | | public CommonResult<Boolean> onReturnQualityFinished(Long returnId, String qualityResult, String reportUrl) { |
| | | returnService.onQualityFinished(returnId, qualityResult, reportUrl); |
| | | return success(true); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<Boolean> onReturnInboundFinished(Long returnId) { |
| | | returnService.onInboundFinished(returnId); |
| | | return success(true); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<Boolean> onRefundCompleted(Long returnId, BigDecimal actualRefundPrice) { |
| | | returnService.onRefundCompleted(returnId, actualRefundPrice); |
| | | return success(true); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<AfterSaleTicketRespDTO> getTicket(Long id) { |
| | | AfterSaleTicketDO ticket = ticketService.getTicket(id); |
| | | return success(BeanUtils.toBean(ticket, AfterSaleTicketRespDTO.class)); |
| | | } |
| | | |
| | | @Override |
| | | public CommonResult<AfterSaleReturnRespDTO> getReturn(Long id) { |
| | | AfterSaleReturnDO returnDO = returnService.getReturn(id); |
| | | return success(BeanUtils.toBean(returnDO, AfterSaleReturnRespDTO.class)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.returnobj; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnRespVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnItemDO; |
| | | import cn.iocoder.yudao.module.aftersales.service.returnobj.AfterSaleReturnService; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.*; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | |
| | | @Tag(name = "管çåå° - å®åéè´§ç³è¯·") |
| | | @RestController |
| | | @RequestMapping("/aftersales/return") |
| | | @Validated |
| | | public class AfterSaleReturnController { |
| | | |
| | | @Resource |
| | | private AfterSaleReturnService returnService; |
| | | |
| | | @Resource |
| | | private CrmCustomerApi customerApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建éè´§ç³è¯·") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:return:create')") |
| | | public CommonResult<Long> createReturn(@Valid @RequestBody AfterSaleReturnSaveReqVO createReqVO) { |
| | | return success(returnService.createReturn(createReqVO, getLoginUserId())); |
| | | } |
| | | |
| | | @PutMapping("/approve") |
| | | @Operation(summary = "å®¡æ ¸éè¿éè´§ç³è¯·") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:return:approve')") |
| | | public CommonResult<Boolean> approveReturn(@RequestParam("id") Long id) { |
| | | returnService.approveReturn(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å¾éè´§ç³è¯·") |
| | | @Parameter(name = "id", description = "éè´§ç³è¯·ç¼å·", required = true, example = "1") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:return:query')") |
| | | public CommonResult<AfterSaleReturnRespVO> getReturn(@RequestParam("id") Long id) { |
| | | AfterSaleReturnDO returnDO = returnService.getReturn(id); |
| | | List<AfterSaleReturnItemDO> items = returnService.getReturnItemListByReturnId(id); |
| | | List<AfterSaleReturnRespVO> enrichedList = buildReturnDetailList(List.of(returnDO)); |
| | | AfterSaleReturnRespVO respVO = enrichedList.get(0); |
| | | respVO.setItems(BeanUtils.toBean(items, AfterSaleReturnRespVO.Item.class)); |
| | | return success(respVO); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "è·å¾éè´§ç³è¯·å页") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:return:query')") |
| | | public CommonResult<PageResult<AfterSaleReturnRespVO>> getReturnPage(@Valid AfterSaleReturnPageReqVO pageReqVO) { |
| | | PageResult<AfterSaleReturnDO> pageResult = returnService.getReturnPage(pageReqVO, getLoginUserId()); |
| | | List<AfterSaleReturnRespVO> list = buildReturnDetailList(pageResult.getList()); |
| | | return success(new PageResult<>(list, pageResult.getTotal())); |
| | | } |
| | | |
| | | // ========== å
鍿¹æ³ï¼æ¹éæ¼è£
å
³èåç§° ========== |
| | | |
| | | private List<AfterSaleReturnRespVO> buildReturnDetailList(List<AfterSaleReturnDO> returnList) { |
| | | if (CollUtil.isEmpty(returnList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // æ¹éå 载客æ·åç§° |
| | | Set<Long> customerIds = convertSet(returnList, AfterSaleReturnDO::getCustomerId); |
| | | Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(customerIds); |
| | | // æ¼è£
åç§°åæ®µ |
| | | return BeanUtils.toBean(returnList, AfterSaleReturnRespVO.class, vo -> { |
| | | CrmCustomerRespDTO customer = customerMap.get(vo.getCustomerId()); |
| | | if (customer != null) vo.setCustomerName(customer.getName()); |
| | | }); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.ToString; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯·å页æ¥è¯¢ VO |
| | | */ |
| | | @Schema(description = "å®åéè´§ç³è¯· - å页æ¥è¯¢ Request VO") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | public class AfterSaleReturnPageReqVO extends PageParam { |
| | | |
| | | @Schema(description = "éè´§åå·", example = "RT20240101000001") |
| | | private String no; |
| | | |
| | | @Schema(description = "å
³èå·¥åç¼å·", example = "1") |
| | | private Long ticketId; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", example = "1") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "éè´§ç¶æ", example = "10") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "åºæ¯ç±»å", example = "1") |
| | | private Integer sceneType; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯·ååº VO |
| | | */ |
| | | @Schema(description = "å®åéè´§ç³è¯· - ååº VO") |
| | | @Data |
| | | public class AfterSaleReturnRespVO { |
| | | |
| | | @Schema(description = "éè´§ç³è¯·ç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "éè´§åå·", example = "RT20240101000001") |
| | | private String no; |
| | | |
| | | @Schema(description = "å
³èå·¥åç¼å·", example = "1") |
| | | private Long ticketId; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", example = "1") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "客æ·åç§°") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "å
³èéå®è®¢åç¼å·", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éè´§ç±»å: 1-鿬¾éè´§ 2-æ¢è´§ 3-ä»
鿬¾", example = "1") |
| | | private Integer returnType; |
| | | |
| | | @Schema(description = "éè´§åå ", example = "产åå¤è§ç¼ºé·") |
| | | private String returnReason; |
| | | |
| | | @Schema(description = "缺é·åç±»", example = "å¤è§ç¼ºé·") |
| | | private String defectCategory; |
| | | |
| | | @Schema(description = "åºéæ»éé¢", example = "1000.00") |
| | | private BigDecimal totalReturnPrice; |
| | | |
| | | @Schema(description = "å®ééé¢", example = "950.00") |
| | | private BigDecimal actualRefundPrice; |
| | | |
| | | @Schema(description = "ç¶æ", example = "10") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "å®¡æ ¸äºº", example = "1") |
| | | private Long auditUserId; |
| | | |
| | | @Schema(description = "å®¡æ ¸æ¶é´") |
| | | private LocalDateTime auditTime; |
| | | |
| | | @Schema(description = "MESéè´§åç¼å·", example = "1") |
| | | private Long mesReturnId; |
| | | |
| | | @Schema(description = "MESéè´§åå·", example = "MES-RT-001") |
| | | private String mesReturnCode; |
| | | |
| | | @Schema(description = "è´¨æ£ç»è®º", example = "åæ ¼") |
| | | private String qualityResult; |
| | | |
| | | @Schema(description = "è´¨æ£æ¥åéä»¶URL") |
| | | private String qualityReportUrl; |
| | | |
| | | @Schema(description = "éè´§å
¥åºå®ææ¶é´") |
| | | private LocalDateTime returnInboundTime; |
| | | |
| | | @Schema(description = "鿬¾/æ¢è´§å®ææ¶é´") |
| | | private LocalDateTime refundTime; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å建è
") |
| | | private String creator; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | | |
| | | @Schema(description = "æ´æ°è
") |
| | | private String updater; |
| | | |
| | | @Schema(description = "æ´æ°æ¶é´") |
| | | private LocalDateTime updateTime; |
| | | |
| | | @Schema(description = "éè´§æç»è¡å表") |
| | | private List<Item> items; |
| | | |
| | | @Schema(description = "éè´§æç»è¡") |
| | | @Data |
| | | public static class Item { |
| | | |
| | | @Schema(description = "ç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "éè´§ç³è¯·ç¼å·", example = "1") |
| | | private Long returnId; |
| | | |
| | | @Schema(description = "å·¥åæç»è¡ç¼å·", example = "1") |
| | | private Long ticketItemId; |
| | | |
| | | @Schema(description = "MDMç©æç¼å·", example = "1") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "ç©æç¼ç ", example = "MAT-001") |
| | | private String itemCode; |
| | | |
| | | @Schema(description = "ç©æåç§°", example = "çµåå
å¨ä»¶") |
| | | private String itemName; |
| | | |
| | | @Schema(description = "æ¹æ¬¡ç¼å·", example = "1") |
| | | private Long batchId; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·", example = "BATCH-2024-001") |
| | | private String batchCode; |
| | | |
| | | @Schema(description = "éè´§æ°é", example = "10.000") |
| | | private BigDecimal returnQuantity; |
| | | |
| | | @Schema(description = "éå®åä»·", example = "100.00") |
| | | private BigDecimal unitPrice; |
| | | |
| | | @Schema(description = "éè´§éé¢", example = "1000.00") |
| | | private BigDecimal returnPrice; |
| | | |
| | | @Schema(description = "MESéè´§åè¡ç¼å·", example = "1") |
| | | private Long mesReturnLineId; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯·ä¿å VO |
| | | */ |
| | | @Schema(description = "å®åéè´§ç³è¯· - ä¿å Request VO") |
| | | @Data |
| | | public class AfterSaleReturnSaveReqVO { |
| | | |
| | | @Schema(description = "éè´§ç³è¯·ç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å
³èå·¥åç¼å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "å
³èå·¥åä¸è½ä¸ºç©º") |
| | | private Long ticketId; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "客æ·ä¸è½ä¸ºç©º") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "å
³èéå®è®¢åç¼å·", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éè´§ç±»å: 1-鿬¾éè´§ 2-æ¢è´§ 3-ä»
鿬¾", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "éè´§ç±»åä¸è½ä¸ºç©º") |
| | | private Integer returnType; |
| | | |
| | | @Schema(description = "éè´§åå ", requiredMode = Schema.RequiredMode.REQUIRED, example = "产åå¤è§ç¼ºé·") |
| | | @NotEmpty(message = "éè´§åå ä¸è½ä¸ºç©º") |
| | | private String returnReason; |
| | | |
| | | @Schema(description = "缺é·åç±»", example = "å¤è§ç¼ºé·") |
| | | private String defectCategory; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | |
| | | @Schema(description = "éè´§æç»è¡å表") |
| | | private List<Item> items; |
| | | |
| | | @Schema(description = "éè´§æç»è¡") |
| | | @Data |
| | | public static class Item { |
| | | |
| | | @Schema(description = "å·¥åæç»è¡ç¼å·", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "å·¥åæç»è¡ä¸è½ä¸ºç©º") |
| | | private Long ticketItemId; |
| | | |
| | | @Schema(description = "MDMç©æç¼å·", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "ç©æä¸è½ä¸ºç©º") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "ç©æç¼ç ", example = "MAT-001") |
| | | private String itemCode; |
| | | |
| | | @Schema(description = "ç©æåç§°", example = "çµåå
å¨ä»¶") |
| | | private String itemName; |
| | | |
| | | @Schema(description = "æ¹æ¬¡ç¼å·", example = "1") |
| | | private Long batchId; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·", example = "BATCH-2024-001") |
| | | private String batchCode; |
| | | |
| | | @Schema(description = "éè´§æ°é", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.000") |
| | | @NotNull(message = "éè´§æ°éä¸è½ä¸ºç©º") |
| | | private BigDecimal returnQuantity; |
| | | |
| | | @Schema(description = "éå®åä»·", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") |
| | | @NotNull(message = "éå®åä»·ä¸è½ä¸ºç©º") |
| | | private BigDecimal unitPrice; |
| | | |
| | | @Schema(description = "éè´§éé¢", example = "1000.00") |
| | | private BigDecimal returnPrice; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.ticket; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketRespVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO; |
| | | import cn.iocoder.yudao.module.aftersales.service.ticket.AfterSaleTicketService; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.validation.Valid; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.*; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | |
| | | @Tag(name = "管çåå° - å®åå·¥å") |
| | | @RestController |
| | | @RequestMapping("/aftersales/ticket") |
| | | @Validated |
| | | public class AfterSaleTicketController { |
| | | |
| | | @Resource |
| | | private AfterSaleTicketService ticketService; |
| | | |
| | | @Resource |
| | | private CrmCustomerApi customerApi; |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建å®åå·¥å") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:create')") |
| | | public CommonResult<Long> createTicket(@Valid @RequestBody AfterSaleTicketSaveReqVO createReqVO) { |
| | | return success(ticketService.createTicket(createReqVO, getLoginUserId())); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Operation(summary = "æ´æ°å®åå·¥å") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> updateTicket(@Valid @RequestBody AfterSaleTicketSaveReqVO updateReqVO) { |
| | | ticketService.updateTicket(updateReqVO); |
| | | return success(true); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Operation(summary = "å é¤å®åå·¥å") |
| | | @Parameter(name = "id", description = "å·¥åç¼å·", required = true) |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:delete')") |
| | | public CommonResult<Boolean> deleteTicket(@RequestParam("id") Long id) { |
| | | ticketService.deleteTicket(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/get") |
| | | @Operation(summary = "è·å¾å®åå·¥å") |
| | | @Parameter(name = "id", description = "å·¥åç¼å·", required = true, example = "1") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:query')") |
| | | public CommonResult<AfterSaleTicketRespVO> getTicket(@RequestParam("id") Long id) { |
| | | AfterSaleTicketDO ticket = ticketService.getTicket(id); |
| | | List<AfterSaleTicketItemDO> items = ticketService.getTicketItemListByTicketId(id); |
| | | // æ¹éå è½½å
³èåç§° |
| | | List<AfterSaleTicketRespVO> enrichedList = buildTicketDetailList(List.of(ticket)); |
| | | AfterSaleTicketRespVO respVO = enrichedList.get(0); |
| | | respVO.setItems(BeanUtils.toBean(items, AfterSaleTicketRespVO.Item.class)); |
| | | return success(respVO); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "è·å¾å®åå·¥åå页") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:query')") |
| | | public CommonResult<PageResult<AfterSaleTicketRespVO>> getTicketPage(@Valid AfterSaleTicketPageReqVO pageReqVO) { |
| | | PageResult<AfterSaleTicketDO> pageResult = ticketService.getTicketPage(pageReqVO, getLoginUserId()); |
| | | List<AfterSaleTicketRespVO> list = buildTicketDetailList(pageResult.getList()); |
| | | return success(new PageResult<>(list, pageResult.getTotal())); |
| | | } |
| | | |
| | | @PostMapping("/assign") |
| | | @Operation(summary = "åé
å¤ç人") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> assignTicket(@RequestParam("id") Long id, |
| | | @RequestParam("handlerUserId") Long handlerUserId) { |
| | | ticketService.assignTicket(id, handlerUserId); |
| | | return success(true); |
| | | } |
| | | |
| | | @PostMapping("/classify") |
| | | @Operation(summary = "é®é¢å¤å®") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> classifyTicket(@RequestParam("id") Long id, |
| | | @RequestParam("issueType") Integer issueType, |
| | | @RequestParam(value = "issueCategory", required = false) String issueCategory, |
| | | @RequestParam(value = "severityLevel", required = false) Integer severityLevel) { |
| | | ticketService.classifyTicket(id, issueType, issueCategory, severityLevel); |
| | | return success(true); |
| | | } |
| | | |
| | | @PutMapping("/resolve") |
| | | @Operation(summary = "å®ç»å·¥å") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> resolveTicket(@RequestParam("id") Long id) { |
| | | ticketService.resolveTicket(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @PutMapping("/close") |
| | | @Operation(summary = "å
³éå·¥å") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> closeTicket(@RequestParam("id") Long id) { |
| | | ticketService.closeTicket(id); |
| | | return success(true); |
| | | } |
| | | |
| | | @PutMapping("/cancel") |
| | | @Operation(summary = "åæ¶å·¥å") |
| | | @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')") |
| | | public CommonResult<Boolean> cancelTicket(@RequestParam("id") Long id) { |
| | | ticketService.cancelTicket(id); |
| | | return success(true); |
| | | } |
| | | |
| | | // ========== å
鍿¹æ³ï¼æ¹éæ¼è£
å
³èåç§° ========== |
| | | |
| | | private List<AfterSaleTicketRespVO> buildTicketDetailList(List<AfterSaleTicketDO> ticketList) { |
| | | if (CollUtil.isEmpty(ticketList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | // 1. æ¹éå 载客æ·åç§° |
| | | Set<Long> customerIds = convertSet(ticketList, AfterSaleTicketDO::getCustomerId); |
| | | Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(customerIds); |
| | | // 2. æ¹éå è½½ç¨æ·åç§°ï¼è´è´£äºº + å¤çäººï¼ |
| | | Set<Long> userIds = new HashSet<>(); |
| | | ticketList.forEach(t -> { |
| | | if (t.getOwnerUserId() != null) userIds.add(t.getOwnerUserId()); |
| | | if (t.getHandlerUserId() != null) userIds.add(t.getHandlerUserId()); |
| | | }); |
| | | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| | | // 3. æ¼è£
åç§°åæ®µ |
| | | return BeanUtils.toBean(ticketList, AfterSaleTicketRespVO.class, vo -> { |
| | | CrmCustomerRespDTO customer = customerMap.get(vo.getCustomerId()); |
| | | if (customer != null) vo.setCustomerName(customer.getName()); |
| | | AdminUserRespDTO ownerUser = userMap.get(vo.getOwnerUserId()); |
| | | if (ownerUser != null) vo.setOwnerUserName(ownerUser.getNickname()); |
| | | AdminUserRespDTO handlerUser = userMap.get(vo.getHandlerUserId()); |
| | | if (handlerUser != null) vo.setHandlerUserName(handlerUser.getNickname()); |
| | | }); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.ToString; |
| | | |
| | | /** |
| | | * å®åå·¥åå页æ¥è¯¢ VO |
| | | */ |
| | | @Schema(description = "å®åå·¥å - å页æ¥è¯¢ Request VO") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | public class AfterSaleTicketPageReqVO extends PageParam { |
| | | |
| | | @Schema(description = "å·¥ååå·", example = "AS20240101000001") |
| | | private String no; |
| | | |
| | | @Schema(description = "å·¥å主é¢", example = "产åå¤è§ç¼ºé·") |
| | | private String name; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", example = "1") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "å·¥åç¶æ", example = "10") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "é®é¢ç±»å", example = "1") |
| | | private Integer issueType; |
| | | |
| | | @Schema(description = "åºæ¯ç±»å", example = "1") |
| | | private Integer sceneType; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åå·¥åååº VO |
| | | */ |
| | | @Schema(description = "å®åå·¥å - ååº VO") |
| | | @Data |
| | | public class AfterSaleTicketRespVO { |
| | | |
| | | @Schema(description = "å·¥åç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å·¥ååå·", example = "AS20240101000001") |
| | | private String no; |
| | | |
| | | @Schema(description = "å·¥å主é¢", example = "产åå¤è§ç¼ºé·") |
| | | private String name; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", example = "1") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "客æ·åç§°") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "è系人ç¼å·", example = "1") |
| | | private Long contactId; |
| | | |
| | | @Schema(description = "è系人åç§°") |
| | | private String contactName; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åå·", example = "SO202401010001") |
| | | private String saleOrderNo; |
| | | |
| | | @Schema(description = "ååç¼å·", example = "1") |
| | | private Long contractId; |
| | | |
| | | @Schema(description = "é®é¢ç±»å: 1-ä¸è¬é®é¢ 2-ç»´ä¿®é®é¢ 3-éè´§é®é¢", example = "1") |
| | | private Integer issueType; |
| | | |
| | | @Schema(description = "é®é¢åç±»", example = "å¤è§ç¼ºé·") |
| | | private String issueCategory; |
| | | |
| | | @Schema(description = "é®é¢æè¿°", example = "æ¶å°è´§ååç°äº§åè¡¨é¢æåç") |
| | | private String issueDescription; |
| | | |
| | | @Schema(description = "严éç¨åº¦: 0-轻微 1-ä¸è¬ 2-严é 3-è´å½", example = "1") |
| | | private Integer severityLevel; |
| | | |
| | | @Schema(description = "ç¶æ: 0-è稿 10-å¤çä¸ 30-å¾
éè´§ 40-å¾
鿬¾/æ¢è´§ 50-å·²å®ç» 60-å·²å
³é 99-已忶", example = "0") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "è´è´£äººç¨æ·ç¼å·", example = "1") |
| | | private Long ownerUserId; |
| | | |
| | | @Schema(description = "è´è´£äººåç§°") |
| | | private String ownerUserName; |
| | | |
| | | @Schema(description = "å¤çäººç¨æ·ç¼å·", example = "2") |
| | | private Long handlerUserId; |
| | | |
| | | @Schema(description = "å¤ç人åç§°") |
| | | private String handlerUserName; |
| | | |
| | | @Schema(description = "BPM 工使µå®ä¾ç¼å·") |
| | | private String processInstanceId; |
| | | |
| | | @Schema(description = "å
³èéè´§ç³è¯·ç¼å·", example = "1") |
| | | private Long returnId; |
| | | |
| | | @Schema(description = "å
³è维修记å½ç¼å·", example = "1") |
| | | private Long repairId; |
| | | |
| | | @Schema(description = "è§£å³æ¶é´") |
| | | private LocalDateTime resolvedTime; |
| | | |
| | | @Schema(description = "å
³éæ¶é´") |
| | | private LocalDateTime closedTime; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å建è
") |
| | | private String creator; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | | |
| | | @Schema(description = "æ´æ°è
") |
| | | private String updater; |
| | | |
| | | @Schema(description = "æ´æ°æ¶é´") |
| | | private LocalDateTime updateTime; |
| | | |
| | | @Schema(description = "æç»è¡å表") |
| | | private List<Item> items; |
| | | |
| | | @Schema(description = "å·¥åæç»è¡") |
| | | @Data |
| | | public static class Item { |
| | | |
| | | @Schema(description = "ç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å·¥åç¼å·", example = "1") |
| | | private Long ticketId; |
| | | |
| | | @Schema(description = "éå®è®¢åè¡ç¼å·", example = "1") |
| | | private Long saleOrderItemId; |
| | | |
| | | @Schema(description = "MDMç©æç¼å·", example = "1") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "ç©æç¼ç ", example = "MAT-001") |
| | | private String itemCode; |
| | | |
| | | @Schema(description = "ç©æåç§°", example = "çµåå
å¨ä»¶") |
| | | private String itemName; |
| | | |
| | | @Schema(description = "çäº§æ¹æ¬¡ç¼å·", example = "1") |
| | | private Long batchId; |
| | | |
| | | @Schema(description = "çäº§æ¹æ¬¡å·", example = "BATCH-2024-001") |
| | | private String batchCode; |
| | | |
| | | @Schema(description = "é宿°é", example = "100.000") |
| | | private BigDecimal saleQuantity; |
| | | |
| | | @Schema(description = "éè´§æ°é", example = "10.000") |
| | | private BigDecimal returnQuantity; |
| | | |
| | | @Schema(description = "æ¯å¦éè¦ç»´ä¿®", example = "false") |
| | | private Boolean needRepair; |
| | | |
| | | @Schema(description = "æ¯å¦éè¦éè´§", example = "true") |
| | | private Boolean needReturn; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åå·¥åä¿å VO |
| | | */ |
| | | @Schema(description = "å®åå·¥å - ä¿å Request VO") |
| | | @Data |
| | | public class AfterSaleTicketSaveReqVO { |
| | | |
| | | @Schema(description = "å·¥åç¼å·", example = "1") |
| | | private Long id; |
| | | |
| | | @Schema(description = "å·¥å主é¢", requiredMode = Schema.RequiredMode.REQUIRED, example = "产åå¤è§ç¼ºé·") |
| | | @NotEmpty(message = "å·¥å主é¢ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "客æ·ç¼å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | @NotNull(message = "客æ·ä¸è½ä¸ºç©º") |
| | | private Long customerId; |
| | | |
| | | @Schema(description = "è系人ç¼å·", example = "1") |
| | | private Long contactId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åå·", example = "SO202401010001") |
| | | private String saleOrderNo; |
| | | |
| | | @Schema(description = "ååç¼å·", example = "1") |
| | | private Long contractId; |
| | | |
| | | @Schema(description = "é®é¢æè¿°", example = "æ¶å°è´§ååç°äº§åè¡¨é¢æåç") |
| | | private String issueDescription; |
| | | |
| | | @Schema(description = "夿³¨", example = "客æ·è¦æ±å°½å¿«å¤ç") |
| | | private String remark; |
| | | |
| | | @Schema(description = "æç»è¡å表") |
| | | private List<Item> items; |
| | | |
| | | @Schema(description = "å·¥åæç»è¡") |
| | | @Data |
| | | public static class Item { |
| | | |
| | | @Schema(description = "éå®è®¢åè¡ç¼å·", example = "1") |
| | | private Long saleOrderItemId; |
| | | |
| | | @Schema(description = "MDMç©æç¼å·", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "ç©æä¸è½ä¸ºç©º") |
| | | private Long itemId; |
| | | |
| | | @Schema(description = "ç©æç¼ç ", example = "MAT-001") |
| | | private String itemCode; |
| | | |
| | | @Schema(description = "ç©æåç§°", example = "çµåå
å¨ä»¶") |
| | | private String itemName; |
| | | |
| | | @Schema(description = "çäº§æ¹æ¬¡ç¼å·", example = "1") |
| | | private Long batchId; |
| | | |
| | | @Schema(description = "çäº§æ¹æ¬¡å·", example = "BATCH-2024-001") |
| | | private String batchCode; |
| | | |
| | | @Schema(description = "é宿°é", example = "100.000") |
| | | private BigDecimal saleQuantity; |
| | | |
| | | @Schema(description = "éè´§æ°é", example = "10.000") |
| | | private BigDecimal returnQuantity; |
| | | |
| | | @Schema(description = "æ¯å¦éè¦ç»´ä¿®", example = "false") |
| | | private Boolean needRepair; |
| | | |
| | | @Schema(description = "æ¯å¦éè¦éè´§", example = "true") |
| | | private Boolean needReturn; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | private String remark; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.permission; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æé DO |
| | | */ |
| | | @TableName("after_sale_permission") |
| | | @KeySequence("after_sale_permission_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSalePermissionDO extends BaseDO { |
| | | |
| | | /** |
| | | * ç¼å·ï¼ä¸»é®èªå¢ |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | |
| | | /** |
| | | * æ°æ®ç±»å |
| | | * |
| | | * æä¸¾ {@link AfterSaleBizTypeEnum} |
| | | */ |
| | | private Integer bizType; |
| | | /** |
| | | * æ°æ®ç¼å· |
| | | * |
| | | * å
³è {@link AfterSaleBizTypeEnum} å¯¹åºæ¨¡å DO ç id åæ®µ |
| | | */ |
| | | private Long bizId; |
| | | |
| | | /** |
| | | * ç¨æ·ç¼å· |
| | | */ |
| | | private Long userId; |
| | | |
| | | /** |
| | | * æéçº§å« |
| | | * |
| | | * æä¸¾ {@link AfterSalePermissionLevelEnum} |
| | | */ |
| | | private Integer level; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.repair; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleRepairStatusEnum; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®åç»´ä¿®è®°å½ DO |
| | | */ |
| | | @TableName("after_sale_repair") |
| | | @KeySequence("after_sale_repair_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSaleRepairDO extends BaseDO { |
| | | |
| | | /** |
| | | * 维修记å½ç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * å
³èå·¥åç¼å·ï¼å
³è after_sale_ticket.id |
| | | */ |
| | | private Long ticketId; |
| | | /** |
| | | * 维修类å: 1-ç°åºç»´ä¿® 2-è¿åç»´ä¿® 3-è¿ç¨æå¯¼ |
| | | */ |
| | | private Integer repairType; |
| | | /** |
| | | * æ
éæè¿° |
| | | */ |
| | | private String faultDescription; |
| | | /** |
| | | * ç»´ä¿®æªæ½ |
| | | */ |
| | | private String repairAction; |
| | | /** |
| | | * ç»´ä¿®ç»æ: 已修å¤/æ æ³ä¿®å¤/é¨åä¿®å¤ |
| | | */ |
| | | private String repairResult; |
| | | /** |
| | | * ç»´ä¿®è´¹ç¨ |
| | | */ |
| | | private BigDecimal repairCost; |
| | | /** |
| | | * 维修人 |
| | | */ |
| | | private Long repairUserId; |
| | | /** |
| | | * ç»´ä¿®ç¶æ |
| | | * |
| | | * æä¸¾ {@link AfterSaleRepairStatusEnum} |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * å¼å§ç»´ä¿®æ¶é´ |
| | | */ |
| | | private LocalDateTime startTime; |
| | | /** |
| | | * å®æç»´ä¿®æ¶é´ |
| | | */ |
| | | private LocalDateTime finishTime; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj; |
| | | |
| | | // 注ï¼package åä½¿ç¨ returnobj é¿å
ä¸ Java å
³é®å return å²çª |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleReturnStatusEnum; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯· DO |
| | | */ |
| | | @TableName("after_sale_return") |
| | | @KeySequence("after_sale_return_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSaleReturnDO extends BaseDO { |
| | | |
| | | /** |
| | | * éè´§ç³è¯·ç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * éè´§åå· |
| | | */ |
| | | private String no; |
| | | /** |
| | | * å
³èå·¥åç¼å·ï¼å
³è after_sale_ticket.id |
| | | */ |
| | | private Long ticketId; |
| | | /** |
| | | * 客æ·ç¼å· |
| | | */ |
| | | private Long customerId; |
| | | /** |
| | | * å
³èéå®è®¢åç¼å· |
| | | */ |
| | | private Long saleOrderId; |
| | | /** |
| | | * éè´§ç±»å: 1-鿬¾éè´§ 2-æ¢è´§ 3-ä»
鿬¾ |
| | | */ |
| | | private Integer returnType; |
| | | /** |
| | | * éè´§åå |
| | | */ |
| | | private String returnReason; |
| | | /** |
| | | * 缺é·åç±» |
| | | */ |
| | | private String defectCategory; |
| | | /** |
| | | * åºéæ»éé¢ |
| | | */ |
| | | private BigDecimal totalReturnPrice; |
| | | /** |
| | | * å®ééé¢ |
| | | */ |
| | | private BigDecimal actualRefundPrice; |
| | | /** |
| | | * éè´§ç¶æ |
| | | * |
| | | * æä¸¾ {@link AfterSaleReturnStatusEnum} |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * å®¡æ ¸äºº |
| | | */ |
| | | private Long auditUserId; |
| | | /** |
| | | * å®¡æ ¸æ¶é´ |
| | | */ |
| | | private LocalDateTime auditTime; |
| | | /** |
| | | * MES éè´§åç¼å·ï¼å
³è mes_wm_return_sales.id |
| | | */ |
| | | private Long mesReturnId; |
| | | /** |
| | | * MES éè´§åå·(åä½) |
| | | */ |
| | | private String mesReturnCode; |
| | | /** |
| | | * è´¨æ£ç»è®º: åæ ¼/ç¹é/éè´§/æ¥åº |
| | | */ |
| | | private String qualityResult; |
| | | /** |
| | | * è´¨æ£æ¥åéä»¶URL |
| | | */ |
| | | private String qualityReportUrl; |
| | | /** |
| | | * éè´§å
¥åºå®ææ¶é´ |
| | | */ |
| | | private LocalDateTime returnInboundTime; |
| | | /** |
| | | * 鿬¾/æ¢è´§å®ææ¶é´ |
| | | */ |
| | | private LocalDateTime refundTime; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * å®åéè´§æç»è¡ DO |
| | | */ |
| | | @TableName("after_sale_return_item") |
| | | @KeySequence("after_sale_return_item_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSaleReturnItemDO extends BaseDO { |
| | | |
| | | /** |
| | | * ç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * éè´§ç³è¯·ç¼å·ï¼å
³è after_sale_return.id |
| | | */ |
| | | private Long returnId; |
| | | /** |
| | | * å·¥åæç»è¡ç¼å· |
| | | */ |
| | | private Long ticketItemId; |
| | | /** |
| | | * MDM ç©æç¼å· |
| | | */ |
| | | private Long itemId; |
| | | /** |
| | | * ç©æç¼ç (åä½) |
| | | */ |
| | | private String itemCode; |
| | | /** |
| | | * ç©æåç§°(åä½) |
| | | */ |
| | | private String itemName; |
| | | /** |
| | | * æ¹æ¬¡ç¼å· |
| | | */ |
| | | private Long batchId; |
| | | /** |
| | | * æ¹æ¬¡å· |
| | | */ |
| | | private String batchCode; |
| | | /** |
| | | * éè´§æ°é |
| | | */ |
| | | private BigDecimal returnQuantity; |
| | | /** |
| | | * éå®åä»· |
| | | */ |
| | | private BigDecimal unitPrice; |
| | | /** |
| | | * éè´§éé¢ |
| | | */ |
| | | private BigDecimal returnPrice; |
| | | /** |
| | | * MES éè´§åè¡ç¼å· |
| | | */ |
| | | private Long mesReturnLineId; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleIssueTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleTicketStatusEnum; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®åå·¥å DO |
| | | */ |
| | | @TableName("after_sale_ticket") |
| | | @KeySequence("after_sale_ticket_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSaleTicketDO extends BaseDO { |
| | | |
| | | /** |
| | | * å·¥åç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * å·¥ååå· |
| | | */ |
| | | private String no; |
| | | /** |
| | | * å·¥å主é¢/æ é¢ |
| | | */ |
| | | private String name; |
| | | /** |
| | | * 客æ·ç¼å·ï¼å
³è crm_customer.id |
| | | */ |
| | | private Long customerId; |
| | | /** |
| | | * è系人ç¼å·ï¼å
³è crm_contact.id |
| | | */ |
| | | private Long contactId; |
| | | /** |
| | | * éå®è®¢åç¼å·ï¼å
³è erp_sale_order.id |
| | | */ |
| | | private Long saleOrderId; |
| | | /** |
| | | * éå®è®¢åå·(åä½) |
| | | */ |
| | | private String saleOrderNo; |
| | | /** |
| | | * ååç¼å·ï¼å
³è crm_contract.id |
| | | */ |
| | | private Long contractId; |
| | | /** |
| | | * é®é¢ç±»å |
| | | * |
| | | * æä¸¾ {@link AfterSaleIssueTypeEnum} |
| | | */ |
| | | private Integer issueType; |
| | | /** |
| | | * é®é¢åç±»: å¤è§ç¼ºé·/åè½æ
é/尺寸åå·®/å
è£
ç ´æ/å
¶ä» |
| | | */ |
| | | private String issueCategory; |
| | | /** |
| | | * é®é¢æè¿° |
| | | */ |
| | | private String issueDescription; |
| | | /** |
| | | * 严éç¨åº¦: 0-轻微 1-ä¸è¬ 2-严é 3-è´å½ |
| | | */ |
| | | private Integer severityLevel; |
| | | /** |
| | | * å·¥åç¶æ |
| | | * |
| | | * æä¸¾ {@link AfterSaleTicketStatusEnum} |
| | | */ |
| | | private Integer status; |
| | | /** |
| | | * è´è´£äººç¨æ·ç¼å· |
| | | */ |
| | | private Long ownerUserId; |
| | | /** |
| | | * å¤çäººç¨æ·ç¼å· |
| | | */ |
| | | private Long handlerUserId; |
| | | /** |
| | | * BPM 工使µå®ä¾ç¼å· |
| | | */ |
| | | private String processInstanceId; |
| | | /** |
| | | * å
³èéè´§ç³è¯·ç¼å·ï¼å
³è after_sale_return.id |
| | | */ |
| | | private Long returnId; |
| | | /** |
| | | * å
³è维修记å½ç¼å·ï¼å
³è after_sale_repair.id |
| | | */ |
| | | private Long repairId; |
| | | /** |
| | | * è§£å³æ¶é´ |
| | | */ |
| | | private LocalDateTime resolvedTime; |
| | | /** |
| | | * å
³éæ¶é´ |
| | | */ |
| | | private LocalDateTime closedTime; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| | | import com.baomidou.mybatisplus.annotation.KeySequence; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * å®åå·¥åæç»è¡ DO |
| | | */ |
| | | @TableName("after_sale_ticket_item") |
| | | @KeySequence("after_sale_ticket_item_seq") |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ToString(callSuper = true) |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AfterSaleTicketItemDO extends BaseDO { |
| | | |
| | | /** |
| | | * ç¼å· |
| | | */ |
| | | @TableId |
| | | private Long id; |
| | | /** |
| | | * å·¥åç¼å·ï¼å
³è after_sale_ticket.id |
| | | */ |
| | | private Long ticketId; |
| | | /** |
| | | * éå®è®¢åè¡ç¼å· |
| | | */ |
| | | private Long saleOrderItemId; |
| | | /** |
| | | * MDM ç©æç¼å· |
| | | */ |
| | | private Long itemId; |
| | | /** |
| | | * ç©æç¼ç (åä½) |
| | | */ |
| | | private String itemCode; |
| | | /** |
| | | * ç©æåç§°(åä½) |
| | | */ |
| | | private String itemName; |
| | | /** |
| | | * çäº§æ¹æ¬¡ç¼å· |
| | | */ |
| | | private Long batchId; |
| | | /** |
| | | * çäº§æ¹æ¬¡å· |
| | | */ |
| | | private String batchCode; |
| | | /** |
| | | * é宿°é |
| | | */ |
| | | private BigDecimal saleQuantity; |
| | | /** |
| | | * éè´§æ°é |
| | | */ |
| | | private BigDecimal returnQuantity; |
| | | /** |
| | | * æ¯å¦éè¦ç»´ä¿® |
| | | */ |
| | | private Boolean needRepair; |
| | | /** |
| | | * æ¯å¦éè¦éè´§ |
| | | */ |
| | | private Boolean needReturn; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.permission; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.permission.AfterSalePermissionDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æé Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSalePermissionMapper extends BaseMapperX<AfterSalePermissionDO> { |
| | | |
| | | default List<AfterSalePermissionDO> selectListByBiz(Integer bizType, Long bizId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSalePermissionDO>() |
| | | .eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .eq(AfterSalePermissionDO::getBizId, bizId)); |
| | | } |
| | | |
| | | default List<AfterSalePermissionDO> selectListByBiz(Integer bizType, Collection<Long> bizIds) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSalePermissionDO>() |
| | | .eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .in(AfterSalePermissionDO::getBizId, bizIds)); |
| | | } |
| | | |
| | | default List<AfterSalePermissionDO> selectListByBizTypeAndUserId(Integer bizType, Long userId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSalePermissionDO>() |
| | | .eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .eq(AfterSalePermissionDO::getUserId, userId)); |
| | | } |
| | | |
| | | default AfterSalePermissionDO selectByBizAndUser(Integer bizType, Long bizId, Long userId) { |
| | | return selectOne(new LambdaQueryWrapperX<AfterSalePermissionDO>() |
| | | .eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .eq(AfterSalePermissionDO::getBizId, bizId) |
| | | .eq(AfterSalePermissionDO::getUserId, userId)); |
| | | } |
| | | |
| | | default void deleteByBiz(Integer bizType, Long bizId) { |
| | | delete(new LambdaQueryWrapperX<AfterSalePermissionDO>() |
| | | .eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .eq(AfterSalePermissionDO::getBizId, bizId)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.repair; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.repair.AfterSaleRepairDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åç»´ä¿®è®°å½ Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSaleRepairMapper extends BaseMapperX<AfterSaleRepairDO> { |
| | | |
| | | default AfterSaleRepairDO selectByTicketId(Long ticketId) { |
| | | return selectOne(AfterSaleRepairDO::getTicketId, ticketId); |
| | | } |
| | | |
| | | default List<AfterSaleRepairDO> selectListByTicketId(Long ticketId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSaleRepairDO>() |
| | | .eq(AfterSaleRepairDO::getTicketId, ticketId)); |
| | | } |
| | | |
| | | default PageResult<AfterSaleRepairDO> selectPage(PageParam pageParam, Long ticketId, Integer status) { |
| | | return selectPage(pageParam, new LambdaQueryWrapperX<AfterSaleRepairDO>() |
| | | .eqIfPresent(AfterSaleRepairDO::getTicketId, ticketId) |
| | | .eqIfPresent(AfterSaleRepairDO::getStatus, status) |
| | | .orderByDesc(AfterSaleRepairDO::getId)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.returnobj; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnItemDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åéè´§æç»è¡ Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSaleReturnItemMapper extends BaseMapperX<AfterSaleReturnItemDO> { |
| | | |
| | | default List<AfterSaleReturnItemDO> selectListByReturnId(Long returnId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSaleReturnItemDO>() |
| | | .eq(AfterSaleReturnItemDO::getReturnId, returnId)); |
| | | } |
| | | |
| | | default void deleteByReturnId(Long returnId) { |
| | | delete(new LambdaQueryWrapperX<AfterSaleReturnItemDO>() |
| | | .eq(AfterSaleReturnItemDO::getReturnId, returnId)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.returnobj; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.util.AfterSalePermissionUtils; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯· Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSaleReturnMapper extends BaseMapperX<AfterSaleReturnDO> { |
| | | |
| | | default AfterSaleReturnDO selectByNo(String no) { |
| | | return selectOne(AfterSaleReturnDO::getNo, no); |
| | | } |
| | | |
| | | default AfterSaleReturnDO selectByTicketId(Long ticketId) { |
| | | return selectOne(AfterSaleReturnDO::getTicketId, ticketId); |
| | | } |
| | | |
| | | default PageResult<AfterSaleReturnDO> selectPage(PageParam pageParam, Long userId, Integer sceneType, |
| | | String no, Long ticketId, |
| | | Long customerId, Integer status) { |
| | | MPJLambdaWrapperX<AfterSaleReturnDO> query = new MPJLambdaWrapperX<>(); |
| | | // æ°æ®æé |
| | | AfterSalePermissionUtils.appendPermissionCondition(query, AfterSaleBizTypeEnum.AFTER_SALE_RETURN.getType(), |
| | | AfterSaleReturnDO::getId, userId, sceneType); |
| | | // æ¥è¯¢æ¡ä»¶ |
| | | query.selectAll(AfterSaleReturnDO.class) |
| | | .likeIfPresent(AfterSaleReturnDO::getNo, no) |
| | | .eqIfPresent(AfterSaleReturnDO::getTicketId, ticketId) |
| | | .eqIfPresent(AfterSaleReturnDO::getCustomerId, customerId) |
| | | .eqIfPresent(AfterSaleReturnDO::getStatus, status) |
| | | .orderByDesc(AfterSaleReturnDO::getId); |
| | | return selectJoinPage(pageParam, AfterSaleReturnDO.class, query); |
| | | } |
| | | |
| | | default AfterSaleReturnDO selectByMesReturnId(Long mesReturnId) { |
| | | return selectOne(AfterSaleReturnDO::getMesReturnId, mesReturnId); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åå·¥åæç»è¡ Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSaleTicketItemMapper extends BaseMapperX<AfterSaleTicketItemDO> { |
| | | |
| | | default List<AfterSaleTicketItemDO> selectListByTicketId(Long ticketId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSaleTicketItemDO>() |
| | | .eq(AfterSaleTicketItemDO::getTicketId, ticketId)); |
| | | } |
| | | |
| | | default void deleteByTicketId(Long ticketId) { |
| | | delete(new LambdaQueryWrapperX<AfterSaleTicketItemDO>() |
| | | .eq(AfterSaleTicketItemDO::getTicketId, ticketId)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.mysql.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.util.AfterSalePermissionUtils; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åå·¥å Mapper |
| | | */ |
| | | @Mapper |
| | | public interface AfterSaleTicketMapper extends BaseMapperX<AfterSaleTicketDO> { |
| | | |
| | | default AfterSaleTicketDO selectByNo(String no) { |
| | | return selectOne(AfterSaleTicketDO::getNo, no); |
| | | } |
| | | |
| | | default PageResult<AfterSaleTicketDO> selectPage(PageParam pageParam, Long userId, Integer sceneType, |
| | | String no, String name, |
| | | Long customerId, Long saleOrderId, |
| | | Integer status, Integer issueType) { |
| | | MPJLambdaWrapperX<AfterSaleTicketDO> query = new MPJLambdaWrapperX<>(); |
| | | // æ°æ®æé |
| | | AfterSalePermissionUtils.appendPermissionCondition(query, AfterSaleBizTypeEnum.AFTER_SALE_TICKET.getType(), |
| | | AfterSaleTicketDO::getId, userId, sceneType); |
| | | // æ¥è¯¢æ¡ä»¶ |
| | | query.selectAll(AfterSaleTicketDO.class) |
| | | .likeIfPresent(AfterSaleTicketDO::getNo, no) |
| | | .likeIfPresent(AfterSaleTicketDO::getName, name) |
| | | .eqIfPresent(AfterSaleTicketDO::getCustomerId, customerId) |
| | | .eqIfPresent(AfterSaleTicketDO::getSaleOrderId, saleOrderId) |
| | | .eqIfPresent(AfterSaleTicketDO::getStatus, status) |
| | | .eqIfPresent(AfterSaleTicketDO::getIssueType, issueType) |
| | | .orderByDesc(AfterSaleTicketDO::getId); |
| | | return selectJoinPage(pageParam, AfterSaleTicketDO.class, query); |
| | | } |
| | | |
| | | default List<AfterSaleTicketDO> selectListByCustomerId(Long customerId) { |
| | | return selectList(new LambdaQueryWrapperX<AfterSaleTicketDO>() |
| | | .eq(AfterSaleTicketDO::getCustomerId, customerId)); |
| | | } |
| | | |
| | | default AfterSaleTicketDO selectBySaleOrderId(Long saleOrderId) { |
| | | return selectOne(AfterSaleTicketDO::getSaleOrderId, saleOrderId); |
| | | } |
| | | |
| | | default Long selectCountByOwnerUserId(Long ownerUserId) { |
| | | return selectCount(AfterSaleTicketDO::getOwnerUserId, ownerUserId); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.redis; |
| | | |
| | | /** |
| | | * å®å模å Redis Key 常é |
| | | */ |
| | | public interface RedisKeyConstants { |
| | | |
| | | /** |
| | | * åºå·çç¼å |
| | | * |
| | | * KEY æ ¼å¼ï¼aftersales:seq_no:{prefix} |
| | | * VALUE æ°æ®æ ¼å¼ï¼ç¼å·èªå¢ |
| | | */ |
| | | String NO = "aftersales:seq_no:"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.dal.redis.no; |
| | | |
| | | import cn.hutool.core.date.DatePattern; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.iocoder.yudao.module.aftersales.dal.redis.RedisKeyConstants; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Repository; |
| | | |
| | | import java.time.Duration; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * å®å模ååå· Redis DAO |
| | | */ |
| | | @Repository |
| | | public class AfterSaleNoRedisDAO { |
| | | |
| | | /** |
| | | * å®åå·¥å {@link cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO} |
| | | */ |
| | | public static final String TICKET_NO_PREFIX = "AS"; |
| | | |
| | | /** |
| | | * éè´§ç³è¯· {@link cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO} |
| | | */ |
| | | public static final String RETURN_NO_PREFIX = "RT"; |
| | | |
| | | @Resource |
| | | private StringRedisTemplate stringRedisTemplate; |
| | | |
| | | /** |
| | | * çæåºå·ï¼ä½¿ç¨å½åæ¥æï¼æ ¼å¼ä¸º {PREFIX} + yyyyMMdd + 6 ä½èªå¢ |
| | | * |
| | | * @param prefix åç¼ |
| | | * @return åºå· |
| | | */ |
| | | public String generate(String prefix) { |
| | | String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN); |
| | | String key = RedisKeyConstants.NO + noPrefix; |
| | | Long no = stringRedisTemplate.opsForValue().increment(key); |
| | | stringRedisTemplate.expire(key, Duration.ofDays(1L)); |
| | | return noPrefix + String.format("%06d", no); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åä¸å¡ç±»åæä¸¾ |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Getter |
| | | public enum AfterSaleBizTypeEnum implements ArrayValuable<Integer> { |
| | | |
| | | AFTER_SALE_TICKET(1, "å®åå·¥å"), |
| | | AFTER_SALE_RETURN(2, "éè´§ç³è¯·"), |
| | | AFTER_SALE_REPAIR(3, "维修记å½"), |
| | | ; |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| | | .map(AfterSaleBizTypeEnum::getType).toArray(Integer[]::new); |
| | | |
| | | private final Integer type; |
| | | private final String name; |
| | | |
| | | public static String getNameByType(Integer type) { |
| | | AfterSaleBizTypeEnum typeEnum = CollUtil.findOne(CollUtil.newArrayList(AfterSaleBizTypeEnum.values()), |
| | | item -> ObjUtil.equal(item.type, type)); |
| | | return typeEnum == null ? null : typeEnum.getName(); |
| | | } |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åé®é¢ç±»åæä¸¾ |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Getter |
| | | public enum AfterSaleIssueTypeEnum implements ArrayValuable<Integer> { |
| | | |
| | | UNCLASSIFIED(0, "æªå¤å®"), |
| | | GENERAL(1, "ä¸è¬é®é¢"), |
| | | REPAIR(2, "ç»´ä¿®é®é¢"), |
| | | RETURN(3, "éè´§é®é¢"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| | | .map(AfterSaleIssueTypeEnum::getType).toArray(Integer[]::new); |
| | | |
| | | private final Integer type; |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åç»´ä¿®ç¶ææä¸¾ |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Getter |
| | | public enum AfterSaleRepairStatusEnum implements ArrayValuable<Integer> { |
| | | |
| | | PENDING(0, "å¾
å¤ç"), |
| | | IN_PROGRESS(10, "ç»´ä¿®ä¸"), |
| | | COMPLETED(20, "已宿"), |
| | | CLOSED(30, "å·²å
³é"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| | | .map(AfterSaleRepairStatusEnum::getStatus).toArray(Integer[]::new); |
| | | |
| | | private final Integer status; |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åéè´§ç¶ææä¸¾ |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Getter |
| | | public enum AfterSaleReturnStatusEnum implements ArrayValuable<Integer> { |
| | | |
| | | DRAFT(0, "è稿"), |
| | | AUDITING(10, "éå®å®¡æ ¸ä¸"), |
| | | APPROVED(20, "å®¡æ ¸éè¿-已忥MES"), |
| | | INSPECTING(30, "æ£éªä¸"), |
| | | INSPECTED(40, "æ£éªå®æ"), |
| | | INBOUND(50, "å·²å
¥åº"), |
| | | REFUNDED(60, "鿬¾/æ¢è´§å®æ"), |
| | | CLOSED(70, "å·²å
³é"), |
| | | CANCELED(99, "已忶"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| | | .map(AfterSaleReturnStatusEnum::getStatus).toArray(Integer[]::new); |
| | | |
| | | private final Integer status; |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åå·¥åç¶ææä¸¾ |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Getter |
| | | public enum AfterSaleTicketStatusEnum implements ArrayValuable<Integer> { |
| | | |
| | | DRAFT(0, "è稿"), |
| | | PROCESSING(10, "å¤çä¸"), |
| | | WAITING_RETURN(30, "å¾
éè´§"), |
| | | WAITING_REFUND(40, "å¾
鿬¾/æ¢è´§"), |
| | | COMPLETED(50, "å·²å®ç»"), |
| | | CLOSED(60, "å·²å
³é"), |
| | | CANCELED(99, "已忶"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| | | .map(AfterSaleTicketStatusEnum::getStatus).toArray(Integer[]::new); |
| | | |
| | | private final Integer status; |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | import cn.iocoder.yudao.framework.common.exception.ErrorCode; |
| | | |
| | | /** |
| | | * å®å模åéè¯¯ç æä¸¾ç±» |
| | | * <p> |
| | | * aftersales ç³»ç»ï¼ä½¿ç¨ 1-022-000-000 段 |
| | | */ |
| | | public interface ErrorCodeConstants { |
| | | |
| | | // ========== å®åå·¥å 1-022-000-000 ========== |
| | | ErrorCode TICKET_NOT_EXISTS = new ErrorCode(1_022_000_000, "å®åå·¥åä¸åå¨"); |
| | | ErrorCode TICKET_NO_EXISTS = new ErrorCode(1_022_000_001, "çæå·¥åå·éå¤ï¼è¯·éè¯"); |
| | | ErrorCode TICKET_DELETE_FAIL_NOT_DRAFT = new ErrorCode(1_022_000_002, "å·¥å䏿¯èç¨¿ç¶æï¼æ æ³å é¤"); |
| | | ErrorCode TICKET_UPDATE_FAIL_STATUS = new ErrorCode(1_022_000_003, "æ´æ°å·¥åç¶æå¤±è´¥ï¼åå ï¼å·²ç»æ¯è¯¥ç¶æ"); |
| | | ErrorCode TICKET_RESOLVE_FAIL = new ErrorCode(1_022_000_004, "å®ç»å·¥å失败ï¼åå ï¼å·¥å䏿¯å¤çä¸ç¶æ"); |
| | | ErrorCode TICKET_CLOSE_FAIL = new ErrorCode(1_022_000_005, "å
³éå·¥å失败ï¼åå ï¼å·¥åæªå®ç»"); |
| | | ErrorCode TICKET_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_022_000_006, "æäº¤å·¥å审æ¹å¤±è´¥ï¼åå ï¼å·¥å䏿¯èç¨¿ç¶æ"); |
| | | ErrorCode TICKET_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_022_000_007, "å®åå·¥åå®¡æ¹æµç¨ä¸åå¨ææªæ¿æ´»ï¼è¯·æ£æ¥ BPM é
ç½®"); |
| | | ErrorCode TICKET_STATUS_ERROR = new ErrorCode(1_022_000_008, "å·¥åå½åç¶æä¸å
è®¸æ¤æä½"); |
| | | |
| | | // ========== å®åå·¥åæç»è¡ 1-022-001-000 ========== |
| | | ErrorCode TICKET_ITEM_NOT_EXISTS = new ErrorCode(1_022_001_000, "å·¥åæç»è¡ä¸åå¨"); |
| | | ErrorCode TICKET_ITEM_EMPTY = new ErrorCode(1_022_001_001, "å·¥åæç»è¡ä¸è½ä¸ºç©º"); |
| | | |
| | | // ========== éè´§ç³è¯· 1-022-002-000 ========== |
| | | ErrorCode RETURN_NOT_EXISTS = new ErrorCode(1_022_002_000, "éè´§ç³è¯·ä¸åå¨"); |
| | | ErrorCode RETURN_NO_EXISTS = new ErrorCode(1_022_002_001, "çæéè´§åå·éå¤ï¼è¯·éè¯"); |
| | | ErrorCode RETURN_APPROVE_FAIL = new ErrorCode(1_022_002_002, "å®¡æ ¸éè´§ç³è¯·å¤±è´¥ï¼åå ï¼ä¸æ¯å¾
å®¡æ ¸ç¶æ"); |
| | | ErrorCode RETURN_ITEM_EMPTY = new ErrorCode(1_022_002_003, "éè´§æç»è¡ä¸è½ä¸ºç©º"); |
| | | ErrorCode RETURN_DELETE_FAIL_NOT_DRAFT = new ErrorCode(1_022_002_004, "éè´§ç³è¯·ä¸æ¯èç¨¿ç¶æï¼æ æ³å é¤"); |
| | | |
| | | // ========== ç»´ä¿®è®°å½ 1-022-003-000 ========== |
| | | ErrorCode REPAIR_NOT_EXISTS = new ErrorCode(1_022_003_000, "维修记å½ä¸åå¨"); |
| | | ErrorCode REPAIR_UPDATE_FAIL_STATUS = new ErrorCode(1_022_003_001, "æ´æ°ç»´ä¿®ç¶æå¤±è´¥ï¼åå ï¼å·²ç»æ¯è¯¥ç¶æ"); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums; |
| | | |
| | | /** |
| | | * å®å模åæä½æ¥å¿å¸¸é |
| | | */ |
| | | public interface LogRecordConstants { |
| | | |
| | | // ======================= å®åå·¥å ======================= |
| | | |
| | | String AFTER_SALE_TICKET_TYPE = "å®åå·¥å"; |
| | | String AFTER_SALE_TICKET_CREATE_SUB_TYPE = "å建å®åå·¥å"; |
| | | String AFTER_SALE_TICKET_CREATE_SUCCESS = "å建äºå®åå·¥åã{{#ticket.name}}ã"; |
| | | String AFTER_SALE_TICKET_UPDATE_SUB_TYPE = "æ´æ°å®åå·¥å"; |
| | | String AFTER_SALE_TICKET_UPDATE_SUCCESS = "æ´æ°äºå®åå·¥åã{{#ticketName}}ã: {_DIFF{#updateReqVO}}"; |
| | | String AFTER_SALE_TICKET_DELETE_SUB_TYPE = "å é¤å®åå·¥å"; |
| | | String AFTER_SALE_TICKET_DELETE_SUCCESS = "å é¤äºå®åå·¥åã{{#ticketName}}ã"; |
| | | String AFTER_SALE_TICKET_ASSIGN_SUB_TYPE = "åé
å¤ç人"; |
| | | String AFTER_SALE_TICKET_ASSIGN_SUCCESS = "å°å®åå·¥åã{{#ticketName}}ãåé
ç»ã{getAdminUserById{#handlerUserId}}ã"; |
| | | String AFTER_SALE_TICKET_CLASSIFY_SUB_TYPE = "é®é¢å¤å®"; |
| | | String AFTER_SALE_TICKET_CLASSIFY_SUCCESS = "对å®åå·¥åã{{#ticketName}}ãè¿è¡äºé®é¢å¤å®ï¼ã{{#issueTypeName}}ã"; |
| | | String AFTER_SALE_TICKET_RESOLVE_SUB_TYPE = "å®ç»å·¥å"; |
| | | String AFTER_SALE_TICKET_RESOLVE_SUCCESS = "å®ç»äºå®åå·¥åã{{#ticketName}}ã"; |
| | | String AFTER_SALE_TICKET_CLOSE_SUB_TYPE = "å
³éå·¥å"; |
| | | String AFTER_SALE_TICKET_CLOSE_SUCCESS = "å
³éäºå®åå·¥åã{{#ticketName}}ã"; |
| | | String AFTER_SALE_TICKET_CANCEL_SUB_TYPE = "åæ¶å·¥å"; |
| | | String AFTER_SALE_TICKET_CANCEL_SUCCESS = "åæ¶äºå®åå·¥åã{{#ticketName}}ã"; |
| | | String AFTER_SALE_TICKET_SUBMIT_SUB_TYPE = "æäº¤å·¥å审æ¹"; |
| | | String AFTER_SALE_TICKET_SUBMIT_SUCCESS = "æäº¤å®åå·¥åã{{#ticketName}}ãå®¡æ¹æå"; |
| | | |
| | | // ======================= éè´§ç³è¯· ======================= |
| | | |
| | | String AFTER_SALE_RETURN_TYPE = "å®åéè´§"; |
| | | String AFTER_SALE_RETURN_CREATE_SUB_TYPE = "å建éè´§ç³è¯·"; |
| | | String AFTER_SALE_RETURN_CREATE_SUCCESS = "å建äºéè´§ç³è¯·ã{{#returnDO.no}}ã"; |
| | | String AFTER_SALE_RETURN_APPROVE_SUB_TYPE = "å®¡æ ¸éè´§ç³è¯·"; |
| | | String AFTER_SALE_RETURN_APPROVE_SUCCESS = "å®¡æ ¸éè¿äºéè´§ç³è¯·ã{{#returnNo}}ãï¼å·²åæ¥å°MESéè´§"; |
| | | String AFTER_SALE_RETURN_DELETE_SUB_TYPE = "å é¤éè´§ç³è¯·"; |
| | | String AFTER_SALE_RETURN_DELETE_SUCCESS = "å é¤äºéè´§ç³è¯·ã{{#returnNo}}ã"; |
| | | |
| | | // ======================= ç»´ä¿®è®°å½ ======================= |
| | | |
| | | String AFTER_SALE_REPAIR_TYPE = "å®åç»´ä¿®"; |
| | | String AFTER_SALE_REPAIR_CREATE_SUB_TYPE = "å建维修记å½"; |
| | | String AFTER_SALE_REPAIR_CREATE_SUCCESS = "å建äºç»´ä¿®è®°å½ã{{#repair.id}}ã"; |
| | | String AFTER_SALE_REPAIR_COMPLETE_SUB_TYPE = "å®æç»´ä¿®"; |
| | | String AFTER_SALE_REPAIR_COMPLETE_SUCCESS = "宿äºç»´ä¿®è®°å½ã{{#repairId}}ãï¼ç»´ä¿®ç»æï¼ã{{#repairResult}}ã"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums.permission; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æéçº§å«æä¸¾ |
| | | * |
| | | * OWNER > WRITE > READ |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum AfterSalePermissionLevelEnum implements ArrayValuable<Integer> { |
| | | |
| | | OWNER(1, "è´è´£äºº"), |
| | | READ(2, "åªè¯»"), |
| | | WRITE(3, "读å"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()).map(AfterSalePermissionLevelEnum::getLevel).toArray(Integer[]::new); |
| | | |
| | | /** |
| | | * çº§å« |
| | | */ |
| | | private final Integer level; |
| | | /** |
| | | * 级å«åç§° |
| | | */ |
| | | private final String name; |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | public static boolean isOwner(Integer level) { |
| | | return ObjUtil.equal(OWNER.level, level); |
| | | } |
| | | |
| | | public static boolean isRead(Integer level) { |
| | | return ObjUtil.equal(READ.level, level); |
| | | } |
| | | |
| | | public static boolean isWrite(Integer level) { |
| | | return ObjUtil.equal(WRITE.level, level); |
| | | } |
| | | |
| | | public static String getNameByLevel(Integer level) { |
| | | AfterSalePermissionLevelEnum typeEnum = CollUtil.findOne(CollUtil.newArrayList(AfterSalePermissionLevelEnum.values()), |
| | | item -> ObjUtil.equal(item.level, level)); |
| | | return typeEnum == null ? null : typeEnum.getName(); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.enums.permission; |
| | | |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * å®å模åå表æ£ç´¢åºæ¯ |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum AfterSaleSceneTypeEnum implements ArrayValuable<Integer> { |
| | | |
| | | OWNER(1, "æè´è´£ç"), |
| | | INVOLVED(2, "æåä¸ç"), |
| | | SUBORDINATE(3, "ä¸å±è´è´£ç"), |
| | | ALL(4, "å
¨é¨"); |
| | | |
| | | public static final Integer[] ARRAYS = Arrays.stream(values()).map(AfterSaleSceneTypeEnum::getType).toArray(Integer[]::new); |
| | | |
| | | /** |
| | | * åºæ¯ç±»å |
| | | */ |
| | | private final Integer type; |
| | | /** |
| | | * åºæ¯åç§° |
| | | */ |
| | | private final String name; |
| | | |
| | | public static boolean isOwner(Integer type) { |
| | | return ObjUtil.equal(OWNER.getType(), type); |
| | | } |
| | | |
| | | public static boolean isInvolved(Integer type) { |
| | | return ObjUtil.equal(INVOLVED.getType(), type); |
| | | } |
| | | |
| | | public static boolean isSubordinate(Integer type) { |
| | | return ObjUtil.equal(SUBORDINATE.getType(), type); |
| | | } |
| | | |
| | | public static boolean isAll(Integer type) { |
| | | return ObjUtil.equal(ALL.getType(), type); |
| | | } |
| | | |
| | | @Override |
| | | public Integer[] array() { |
| | | return ARRAYS; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.permission; |
| | | |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.permission.AfterSalePermissionDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.bo.AfterSalePermissionCreateReqBO; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æé Service æ¥å£ |
| | | */ |
| | | public interface AfterSalePermissionService { |
| | | |
| | | /** |
| | | * åå»ºæ°æ®æéï¼è´è´£äººæéï¼ |
| | | * |
| | | * @param createReqBO åå»ºä¿¡æ¯ |
| | | * @return ç¼å· |
| | | */ |
| | | Long createPermission(AfterSalePermissionCreateReqBO createReqBO); |
| | | |
| | | /** |
| | | * å 餿°æ®æé |
| | | * |
| | | * @param bizType æ°æ®ç±»åï¼å
³è {@link AfterSaleBizTypeEnum} |
| | | * @param bizId æ°æ®ç¼å· |
| | | */ |
| | | void deletePermission(Integer bizType, Long bizId); |
| | | |
| | | /** |
| | | * è·åæ°æ®æéå表 |
| | | * |
| | | * @param bizType æ°æ®ç±»å |
| | | * @param bizId æ°æ®ç¼å· |
| | | * @return æéå表 |
| | | */ |
| | | List<AfterSalePermissionDO> getPermissionListByBiz(Integer bizType, Long bizId); |
| | | |
| | | /** |
| | | * è·åæ°æ®æéåè¡¨ï¼æ¹éï¼ |
| | | * |
| | | * @param bizType æ°æ®ç±»å |
| | | * @param bizIds æ°æ®ç¼å·å表 |
| | | * @return æéå表 |
| | | */ |
| | | List<AfterSalePermissionDO> getPermissionListByBiz(Integer bizType, Collection<Long> bizIds); |
| | | |
| | | /** |
| | | * æ ¡éªæ¯å¦ææå®æ°æ®çæä½æé |
| | | * |
| | | * @param bizType æ°æ®ç±»å |
| | | * @param bizId æ°æ®ç¼å· |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @param level æéçº§å« |
| | | * @return æ¯å¦ææé |
| | | */ |
| | | boolean hasPermission(Integer bizType, Long bizId, Long userId, AfterSalePermissionLevelEnum level); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.permission; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.permission.AfterSalePermissionDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.permission.AfterSalePermissionMapper; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.bo.AfterSalePermissionCreateReqBO; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æé Service å®ç°ç±» |
| | | */ |
| | | @Service |
| | | @Validated |
| | | public class AfterSalePermissionServiceImpl implements AfterSalePermissionService { |
| | | |
| | | @Resource |
| | | private AfterSalePermissionMapper afterSalePermissionMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createPermission(AfterSalePermissionCreateReqBO createReqBO) { |
| | | AfterSalePermissionDO permission = BeanUtils.toBean(createReqBO, AfterSalePermissionDO.class); |
| | | afterSalePermissionMapper.insert(permission); |
| | | return permission.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deletePermission(Integer bizType, Long bizId) { |
| | | afterSalePermissionMapper.deleteByBiz(bizType, bizId); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSalePermissionDO> getPermissionListByBiz(Integer bizType, Long bizId) { |
| | | return afterSalePermissionMapper.selectListByBiz(bizType, bizId); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSalePermissionDO> getPermissionListByBiz(Integer bizType, Collection<Long> bizIds) { |
| | | if (CollUtil.isEmpty(bizIds)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | return afterSalePermissionMapper.selectListByBiz(bizType, bizIds); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasPermission(Integer bizType, Long bizId, Long userId, AfterSalePermissionLevelEnum level) { |
| | | List<AfterSalePermissionDO> permissionList = getPermissionListByBiz(bizType, bizId); |
| | | return permissionList.stream() |
| | | .anyMatch(p -> ObjUtil.equal(p.getUserId(), userId) |
| | | && ObjUtil.equal(p.getLevel(), level.getLevel())); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.permission.bo; |
| | | |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æéå建 Request BO |
| | | */ |
| | | @Data |
| | | public class AfterSalePermissionCreateReqBO { |
| | | |
| | | /** |
| | | * æ°æ®ç±»åï¼å
³è {@link AfterSaleBizTypeEnum} |
| | | */ |
| | | @NotNull(message = "æ°æ®ç±»åä¸è½ä¸ºç©º") |
| | | private Integer bizType; |
| | | |
| | | /** |
| | | * æ°æ®ç¼å· |
| | | */ |
| | | @NotNull(message = "æ°æ®ç¼å·ä¸è½ä¸ºç©º") |
| | | private Long bizId; |
| | | |
| | | /** |
| | | * ç¨æ·ç¼å· |
| | | */ |
| | | @NotNull(message = "ç¨æ·ç¼å·ä¸è½ä¸ºç©º") |
| | | private Long userId; |
| | | |
| | | /** |
| | | * æé级å«ï¼å
³è {@link AfterSalePermissionLevelEnum} |
| | | */ |
| | | @NotNull(message = "æé级å«ä¸è½ä¸ºç©º") |
| | | private Integer level; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.repair; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.repair.AfterSaleRepairDO; |
| | | import jakarta.validation.Valid; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åç»´ä¿®è®°å½ Service æ¥å£ |
| | | */ |
| | | public interface AfterSaleRepairService { |
| | | |
| | | /** |
| | | * åå»ºç»´ä¿®è®°å½ |
| | | * |
| | | * @param repairDO ç»´ä¿®ä¿¡æ¯ |
| | | * @return ç¼å· |
| | | */ |
| | | Long createRepair(@Valid AfterSaleRepairDO repairDO); |
| | | |
| | | /** |
| | | * æ´æ°ç»´ä¿®è®°å½ |
| | | * |
| | | * @param repairDO æ´æ°ä¿¡æ¯ |
| | | */ |
| | | void updateRepair(@Valid AfterSaleRepairDO repairDO); |
| | | |
| | | /** |
| | | * å®æç»´ä¿® |
| | | * |
| | | * @param id 维修记å½ç¼å· |
| | | */ |
| | | void completeRepair(Long id); |
| | | |
| | | /** |
| | | * è·å¾ç»´ä¿®è®°å½ |
| | | * |
| | | * @param id ç¼å· |
| | | * @return ç»´ä¿®è®°å½ |
| | | */ |
| | | AfterSaleRepairDO getRepair(Long id); |
| | | |
| | | /** |
| | | * è·å¾ç»´ä¿®è®°å½å表 |
| | | * |
| | | * @param ids ç¼å·å表 |
| | | * @return 维修记å½å表 |
| | | */ |
| | | List<AfterSaleRepairDO> getRepairList(Collection<Long> ids); |
| | | |
| | | /** |
| | | * è·å¾ç»´ä¿®è®°å½å页 |
| | | * |
| | | * @param pageParam å页忰 |
| | | * @param ticketId å
³èå·¥åç¼å· |
| | | * @param status ç»´ä¿®ç¶æ |
| | | * @return 维修记å½å页 |
| | | */ |
| | | PageResult<AfterSaleRepairDO> getRepairPage(Object pageParam, Long ticketId, Integer status); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.repair; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.repair.AfterSaleRepairDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.repair.AfterSaleRepairMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketMapper; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleRepairStatusEnum; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.aftersales.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | | * å®åç»´ä¿®è®°å½ Service å®ç°ç±» |
| | | */ |
| | | @Service |
| | | @Validated |
| | | @Slf4j |
| | | public class AfterSaleRepairServiceImpl implements AfterSaleRepairService { |
| | | |
| | | @Resource |
| | | private AfterSaleRepairMapper repairMapper; |
| | | @Resource |
| | | private AfterSaleTicketMapper ticketMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createRepair(AfterSaleRepairDO repairDO) { |
| | | // æ ¡éªå·¥ååå¨ |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(repairDO.getTicketId()); |
| | | if (ticket == null) { |
| | | throw exception(TICKET_NOT_EXISTS); |
| | | } |
| | | |
| | | repairDO.setStatus(AfterSaleRepairStatusEnum.PENDING.getStatus()); |
| | | repairMapper.insert(repairDO); |
| | | |
| | | // æ´æ°å·¥åå
³èç»´ä¿®è®°å½ |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(ticket.getId()) |
| | | .setRepairId(repairDO.getId())); |
| | | |
| | | return repairDO.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateRepair(AfterSaleRepairDO repairDO) { |
| | | validateRepairExists(repairDO.getId()); |
| | | repairMapper.updateById(repairDO); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void completeRepair(Long id) { |
| | | AfterSaleRepairDO repair = validateRepairExists(id); |
| | | repairMapper.updateById(new AfterSaleRepairDO().setId(id) |
| | | .setStatus(AfterSaleRepairStatusEnum.COMPLETED.getStatus()) |
| | | .setFinishTime(LocalDateTime.now())); |
| | | // æ´æ°å·¥åç¶æ |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(repair.getTicketId()); |
| | | if (ticket != null) { |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(ticket.getId()) |
| | | .setStatus(cn.iocoder.yudao.module.aftersales.enums.AfterSaleTicketStatusEnum.COMPLETED.getStatus()) |
| | | .setResolvedTime(LocalDateTime.now())); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public AfterSaleRepairDO getRepair(Long id) { |
| | | return validateRepairExists(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSaleRepairDO> getRepairList(Collection<Long> ids) { |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return List.of(); |
| | | } |
| | | return repairMapper.selectBatchIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<AfterSaleRepairDO> getRepairPage(Object pageParam, Long ticketId, Integer status) { |
| | | if (pageParam instanceof PageParam) { |
| | | return repairMapper.selectPage((PageParam) pageParam, ticketId, status); |
| | | } |
| | | return repairMapper.selectPage(new PageParam(), ticketId, status); |
| | | } |
| | | |
| | | // ========== å
鍿¹æ³ ========== |
| | | |
| | | private AfterSaleRepairDO validateRepairExists(Long id) { |
| | | AfterSaleRepairDO repair = repairMapper.selectById(id); |
| | | if (repair == null) { |
| | | throw exception(REPAIR_NOT_EXISTS); |
| | | } |
| | | return repair; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.returnobj; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnItemDO; |
| | | import jakarta.validation.Valid; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯· Service æ¥å£ |
| | | */ |
| | | public interface AfterSaleReturnService { |
| | | |
| | | /** |
| | | * å建éè´§ç³è¯· |
| | | * |
| | | * @param createReqVO åå»ºä¿¡æ¯ |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @return ç¼å· |
| | | */ |
| | | Long createReturn(@Valid AfterSaleReturnSaveReqVO createReqVO, Long userId); |
| | | |
| | | /** |
| | | * å®¡æ ¸éè¿ï¼è§¦å MES éè´§æµç¨ï¼ |
| | | * |
| | | * @param id éè´§ç³è¯·ç¼å· |
| | | */ |
| | | void approveReturn(Long id); |
| | | |
| | | /** |
| | | * è·å¾éè´§ç³è¯· |
| | | * |
| | | * @param id ç¼å· |
| | | * @return éè´§ç³è¯· |
| | | */ |
| | | AfterSaleReturnDO getReturn(Long id); |
| | | |
| | | /** |
| | | * è·å¾éè´§ç³è¯·å表 |
| | | * |
| | | * @param ids ç¼å·å表 |
| | | * @return éè´§ç³è¯·å表 |
| | | */ |
| | | List<AfterSaleReturnDO> getReturnList(Collection<Long> ids); |
| | | |
| | | /** |
| | | * è·å¾éè´§ç³è¯·å页 |
| | | * |
| | | * @param pageReqVO å页æ¥è¯¢ |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @return éè´§ç³è¯·å页 |
| | | */ |
| | | PageResult<AfterSaleReturnDO> getReturnPage(AfterSaleReturnPageReqVO pageReqVO, Long userId); |
| | | |
| | | /** |
| | | * è·å¾éè´§æç»è¡å表 |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | * @return æç»è¡å表 |
| | | */ |
| | | List<AfterSaleReturnItemDO> getReturnItemListByReturnId(Long returnId); |
| | | |
| | | /** |
| | | * MES è´¨æ£å®æåè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | * @param qualityResult è´¨æ£ç»è®º |
| | | * @param reportUrl è´¨æ£æ¥å URL |
| | | */ |
| | | void onQualityFinished(Long returnId, String qualityResult, String reportUrl); |
| | | |
| | | /** |
| | | * MES éè´§å
¥åºå®æåè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | */ |
| | | void onInboundFinished(Long returnId); |
| | | |
| | | /** |
| | | * ERP 鿬¾å®æåè° |
| | | * |
| | | * @param returnId éè´§ç³è¯·ç¼å· |
| | | * @param actualRefundPrice å®ééé¢ |
| | | */ |
| | | void onRefundCompleted(Long returnId, BigDecimal actualRefundPrice); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.returnobj; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnItemDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.returnobj.AfterSaleReturnItemMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.returnobj.AfterSaleReturnMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.redis.no.AfterSaleNoRedisDAO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleReturnStatusEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleTicketStatusEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.AfterSalePermissionService; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.bo.AfterSalePermissionCreateReqBO; |
| | | import cn.iocoder.yudao.module.mes.api.returnsales.MesWmReturnSalesApi; |
| | | import cn.iocoder.yudao.module.mes.api.returnsales.dto.MesWmReturnSalesCreateReqDTO; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.aftersales.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | | * å®åéè´§ç³è¯· Service å®ç°ç±» |
| | | */ |
| | | @Service |
| | | @Validated |
| | | @Slf4j |
| | | public class AfterSaleReturnServiceImpl implements AfterSaleReturnService { |
| | | |
| | | @Resource |
| | | private AfterSaleReturnMapper returnMapper; |
| | | @Resource |
| | | private AfterSaleReturnItemMapper returnItemMapper; |
| | | @Resource |
| | | private AfterSaleTicketMapper ticketMapper; |
| | | |
| | | @Resource |
| | | private AfterSaleNoRedisDAO noRedisDAO; |
| | | |
| | | @Resource |
| | | private AfterSalePermissionService permissionService; |
| | | |
| | | @Resource |
| | | private MesWmReturnSalesApi mesWmReturnSalesApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createReturn(AfterSaleReturnSaveReqVO createReqVO, Long userId) { |
| | | // 1. æ ¡éªå·¥ååå¨ |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(createReqVO.getTicketId()); |
| | | if (ticket == null) { |
| | | throw exception(TICKET_NOT_EXISTS); |
| | | } |
| | | |
| | | // 2. çæåå· |
| | | String no = noRedisDAO.generate(AfterSaleNoRedisDAO.RETURN_NO_PREFIX); |
| | | if (returnMapper.selectByNo(no) != null) { |
| | | throw exception(RETURN_NO_EXISTS); |
| | | } |
| | | |
| | | // 3. 计ç®åºéæ»éé¢ |
| | | BigDecimal totalReturnPrice = BigDecimal.ZERO; |
| | | if (CollUtil.isNotEmpty(createReqVO.getItems())) { |
| | | totalReturnPrice = createReqVO.getItems().stream() |
| | | .map(item -> item.getReturnPrice() != null ? item.getReturnPrice() : BigDecimal.ZERO) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | } |
| | | |
| | | // 4. æå
¥éè´§ç³è¯· |
| | | AfterSaleReturnDO returnDO = BeanUtils.toBean(createReqVO, AfterSaleReturnDO.class) |
| | | .setNo(no) |
| | | .setTotalReturnPrice(totalReturnPrice) |
| | | .setStatus(AfterSaleReturnStatusEnum.DRAFT.getStatus()); |
| | | returnMapper.insert(returnDO); |
| | | |
| | | // 5. æå
¥éè´§æç»è¡ |
| | | if (CollUtil.isNotEmpty(createReqVO.getItems())) { |
| | | createReqVO.getItems().forEach(item -> { |
| | | AfterSaleReturnItemDO itemDO = BeanUtils.toBean(item, AfterSaleReturnItemDO.class); |
| | | itemDO.setReturnId(returnDO.getId()); |
| | | returnItemMapper.insert(itemDO); |
| | | }); |
| | | } |
| | | |
| | | // 6. åå»ºæ°æ®æé |
| | | AfterSalePermissionCreateReqBO permBO = new AfterSalePermissionCreateReqBO(); |
| | | permBO.setBizType(AfterSaleBizTypeEnum.AFTER_SALE_RETURN.getType()); |
| | | permBO.setBizId(returnDO.getId()); |
| | | permBO.setUserId(userId); |
| | | permBO.setLevel(AfterSalePermissionLevelEnum.OWNER.getLevel()); |
| | | permissionService.createPermission(permBO); |
| | | |
| | | // 7. æ´æ°å·¥åç¶æä¸ºå¾
éè´§ |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(ticket.getId()) |
| | | .setReturnId(returnDO.getId()) |
| | | .setStatus(AfterSaleTicketStatusEnum.WAITING_RETURN.getStatus())); |
| | | |
| | | return returnDO.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void approveReturn(Long id) { |
| | | // 1. æ ¡éªéè´§ç³è¯· |
| | | AfterSaleReturnDO returnDO = validateReturnExists(id); |
| | | if (!AfterSaleReturnStatusEnum.DRAFT.getStatus().equals(returnDO.getStatus())) { |
| | | throw exception(RETURN_APPROVE_FAIL); |
| | | } |
| | | |
| | | // 2. è·åå
³èå·¥åï¼ç¨äºè·åéå®è®¢åå·çåä½ä¿¡æ¯ï¼ |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(returnDO.getTicketId()); |
| | | |
| | | // 3. è°ç¨ MES å建éå®éè´§å |
| | | MesWmReturnSalesCreateReqDTO mesReqDTO = new MesWmReturnSalesCreateReqDTO(); |
| | | mesReqDTO.setCode(returnDO.getNo()); |
| | | mesReqDTO.setName("å®åéè´§-" + returnDO.getNo()); |
| | | mesReqDTO.setSaleOrderId(returnDO.getSaleOrderId()); |
| | | mesReqDTO.setSalesOrderCode(ticket != null ? ticket.getSaleOrderNo() : null); |
| | | mesReqDTO.setClientId(returnDO.getCustomerId()); |
| | | mesReqDTO.setReturnDate(LocalDate.now()); |
| | | mesReqDTO.setReturnReason(returnDO.getReturnReason()); |
| | | mesReqDTO.setRemark("å®åå·¥åéè´§ - å·¥åå·: " + (ticket != null ? ticket.getNo() : "")); |
| | | mesReqDTO.setAfterSaleReturnId(returnDO.getId()); |
| | | Long mesReturnId = mesWmReturnSalesApi.createReturnSales(mesReqDTO); |
| | | |
| | | // 4. æ´æ°éè´§ç³è¯·ç¶æ |
| | | returnMapper.updateById(new AfterSaleReturnDO().setId(id) |
| | | .setStatus(AfterSaleReturnStatusEnum.APPROVED.getStatus()) |
| | | .setMesReturnId(mesReturnId) |
| | | .setMesReturnCode(returnDO.getNo()) |
| | | .setAuditTime(LocalDateTime.now())); |
| | | } |
| | | |
| | | @Override |
| | | public AfterSaleReturnDO getReturn(Long id) { |
| | | return validateReturnExists(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSaleReturnDO> getReturnList(Collection<Long> ids) { |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return List.of(); |
| | | } |
| | | return returnMapper.selectBatchIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<AfterSaleReturnDO> getReturnPage(AfterSaleReturnPageReqVO pageReqVO, Long userId) { |
| | | return returnMapper.selectPage(pageReqVO, userId, pageReqVO.getSceneType(), |
| | | pageReqVO.getNo(), pageReqVO.getTicketId(), |
| | | pageReqVO.getCustomerId(), pageReqVO.getStatus()); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSaleReturnItemDO> getReturnItemListByReturnId(Long returnId) { |
| | | return returnItemMapper.selectListByReturnId(returnId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void onQualityFinished(Long returnId, String qualityResult, String reportUrl) { |
| | | AfterSaleReturnDO returnDO = validateReturnExists(returnId); |
| | | returnMapper.updateById(new AfterSaleReturnDO().setId(returnId) |
| | | .setQualityResult(qualityResult) |
| | | .setQualityReportUrl(reportUrl) |
| | | .setStatus(AfterSaleReturnStatusEnum.INSPECTED.getStatus())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void onInboundFinished(Long returnId) { |
| | | AfterSaleReturnDO returnDO = validateReturnExists(returnId); |
| | | returnMapper.updateById(new AfterSaleReturnDO().setId(returnId) |
| | | .setStatus(AfterSaleReturnStatusEnum.INBOUND.getStatus()) |
| | | .setReturnInboundTime(LocalDateTime.now())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void onRefundCompleted(Long returnId, BigDecimal actualRefundPrice) { |
| | | AfterSaleReturnDO returnDO = validateReturnExists(returnId); |
| | | returnMapper.updateById(new AfterSaleReturnDO().setId(returnId) |
| | | .setActualRefundPrice(actualRefundPrice) |
| | | .setStatus(AfterSaleReturnStatusEnum.REFUNDED.getStatus()) |
| | | .setRefundTime(LocalDateTime.now())); |
| | | |
| | | // æ´æ°å
³èå·¥åç¶æä¸ºå¾
鿬¾/æ¢è´§å®æ |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(returnDO.getTicketId()); |
| | | if (ticket != null) { |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(ticket.getId()) |
| | | .setStatus(AfterSaleTicketStatusEnum.WAITING_REFUND.getStatus())); |
| | | } |
| | | } |
| | | |
| | | // ========== å
鍿¹æ³ ========== |
| | | |
| | | private AfterSaleReturnDO validateReturnExists(Long id) { |
| | | AfterSaleReturnDO returnDO = returnMapper.selectById(id); |
| | | if (returnDO == null) { |
| | | throw exception(RETURN_NOT_EXISTS); |
| | | } |
| | | return returnDO; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.ticket; |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO; |
| | | import jakarta.validation.Valid; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®åå·¥å Service æ¥å£ |
| | | */ |
| | | public interface AfterSaleTicketService { |
| | | |
| | | /** |
| | | * å建工å |
| | | * |
| | | * @param createReqVO åå»ºä¿¡æ¯ |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @return ç¼å· |
| | | */ |
| | | Long createTicket(@Valid AfterSaleTicketSaveReqVO createReqVO, Long userId); |
| | | |
| | | /** |
| | | * æ´æ°å·¥å |
| | | * |
| | | * @param updateReqVO æ´æ°ä¿¡æ¯ |
| | | */ |
| | | void updateTicket(@Valid AfterSaleTicketSaveReqVO updateReqVO); |
| | | |
| | | /** |
| | | * å é¤å·¥å |
| | | * |
| | | * @param id ç¼å· |
| | | */ |
| | | void deleteTicket(Long id); |
| | | |
| | | /** |
| | | * è·å¾å·¥å |
| | | * |
| | | * @param id ç¼å· |
| | | * @return å·¥å |
| | | */ |
| | | AfterSaleTicketDO getTicket(Long id); |
| | | |
| | | /** |
| | | * è·å¾å·¥åå表 |
| | | * |
| | | * @param ids ç¼å·å表 |
| | | * @return å·¥åå表 |
| | | */ |
| | | List<AfterSaleTicketDO> getTicketList(Collection<Long> ids); |
| | | |
| | | /** |
| | | * è·å¾å·¥åå页 |
| | | * |
| | | * @param pageReqVO å页æ¥è¯¢ |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @return å·¥åå页 |
| | | */ |
| | | PageResult<AfterSaleTicketDO> getTicketPage(AfterSaleTicketPageReqVO pageReqVO, Long userId); |
| | | |
| | | /** |
| | | * è·å¾å·¥åæç»è¡å表 |
| | | * |
| | | * @param ticketId å·¥åç¼å· |
| | | * @return æç»è¡å表 |
| | | */ |
| | | List<AfterSaleTicketItemDO> getTicketItemListByTicketId(Long ticketId); |
| | | |
| | | /** |
| | | * åé
å¤ç人 |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | * @param handlerUserId å¤çäººç¨æ·ç¼å· |
| | | */ |
| | | void assignTicket(Long id, Long handlerUserId); |
| | | |
| | | /** |
| | | * é®é¢å¤å®ï¼ç¡®å®é®é¢ç±»åãåç±»ã严éç¨åº¦ï¼ |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | * @param issueType é®é¢ç±»å |
| | | * @param issueCategory é®é¢åç±» |
| | | * @param severityLevel 严éç¨åº¦ |
| | | */ |
| | | void classifyTicket(Long id, Integer issueType, String issueCategory, Integer severityLevel); |
| | | |
| | | /** |
| | | * å®ç»å·¥å |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | */ |
| | | void resolveTicket(Long id); |
| | | |
| | | /** |
| | | * å
³éå·¥å |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | */ |
| | | void closeTicket(Long id); |
| | | |
| | | /** |
| | | * åæ¶å·¥å |
| | | * |
| | | * @param id å·¥åç¼å· |
| | | */ |
| | | void cancelTicket(Long id); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.service.ticket; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketPageReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketSaveReqVO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketItemMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketMapper; |
| | | import cn.iocoder.yudao.module.aftersales.dal.redis.no.AfterSaleNoRedisDAO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleTicketStatusEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.AfterSalePermissionService; |
| | | import cn.iocoder.yudao.module.aftersales.service.permission.bo.AfterSalePermissionCreateReqBO; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.aftersales.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | | * å®åå·¥å Service å®ç°ç±» |
| | | */ |
| | | @Service |
| | | @Validated |
| | | @Slf4j |
| | | public class AfterSaleTicketServiceImpl implements AfterSaleTicketService { |
| | | |
| | | @Resource |
| | | private AfterSaleTicketMapper ticketMapper; |
| | | @Resource |
| | | private AfterSaleTicketItemMapper ticketItemMapper; |
| | | |
| | | @Resource |
| | | private AfterSaleNoRedisDAO noRedisDAO; |
| | | |
| | | @Resource |
| | | private AfterSalePermissionService permissionService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createTicket(AfterSaleTicketSaveReqVO createReqVO, Long userId) { |
| | | // 1. çæåå· |
| | | String no = noRedisDAO.generate(AfterSaleNoRedisDAO.TICKET_NO_PREFIX); |
| | | if (ticketMapper.selectByNo(no) != null) { |
| | | throw exception(TICKET_NO_EXISTS); |
| | | } |
| | | |
| | | // 2. æå
¥å·¥å |
| | | AfterSaleTicketDO ticket = BeanUtils.toBean(createReqVO, AfterSaleTicketDO.class) |
| | | .setNo(no) |
| | | .setStatus(AfterSaleTicketStatusEnum.DRAFT.getStatus()) |
| | | .setOwnerUserId(userId); |
| | | ticketMapper.insert(ticket); |
| | | |
| | | // 3. æå
¥æç»è¡ |
| | | if (CollUtil.isNotEmpty(createReqVO.getItems())) { |
| | | createReqVO.getItems().forEach(item -> { |
| | | AfterSaleTicketItemDO itemDO = BeanUtils.toBean(item, AfterSaleTicketItemDO.class); |
| | | itemDO.setTicketId(ticket.getId()); |
| | | ticketItemMapper.insert(itemDO); |
| | | }); |
| | | } |
| | | |
| | | // 4. åå»ºæ°æ®æéï¼è´è´£äººï¼ |
| | | AfterSalePermissionCreateReqBO permBO = new AfterSalePermissionCreateReqBO(); |
| | | permBO.setBizType(AfterSaleBizTypeEnum.AFTER_SALE_TICKET.getType()); |
| | | permBO.setBizId(ticket.getId()); |
| | | permBO.setUserId(userId); |
| | | permBO.setLevel(AfterSalePermissionLevelEnum.OWNER.getLevel()); |
| | | permissionService.createPermission(permBO); |
| | | |
| | | return ticket.getId(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateTicket(AfterSaleTicketSaveReqVO updateReqVO) { |
| | | // 1. æ ¡éªåå¨ |
| | | AfterSaleTicketDO ticket = validateTicketExists(updateReqVO.getId()); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.DRAFT); |
| | | |
| | | // 2. æ´æ°å·¥å |
| | | AfterSaleTicketDO updateObj = BeanUtils.toBean(updateReqVO, AfterSaleTicketDO.class); |
| | | ticketMapper.updateById(updateObj); |
| | | |
| | | // 3. æ´æ°æç»è¡ï¼å
å åå¢ï¼ |
| | | ticketItemMapper.deleteByTicketId(ticket.getId()); |
| | | if (CollUtil.isNotEmpty(updateReqVO.getItems())) { |
| | | updateReqVO.getItems().forEach(item -> { |
| | | AfterSaleTicketItemDO itemDO = BeanUtils.toBean(item, AfterSaleTicketItemDO.class); |
| | | itemDO.setTicketId(ticket.getId()); |
| | | ticketItemMapper.insert(itemDO); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteTicket(Long id) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.DRAFT, AfterSaleTicketStatusEnum.CANCELED); |
| | | // 软å é¤ |
| | | ticketMapper.deleteById(id); |
| | | ticketItemMapper.deleteByTicketId(id); |
| | | permissionService.deletePermission(AfterSaleBizTypeEnum.AFTER_SALE_TICKET.getType(), id); |
| | | } |
| | | |
| | | @Override |
| | | public AfterSaleTicketDO getTicket(Long id) { |
| | | return validateTicketExists(id); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSaleTicketDO> getTicketList(Collection<Long> ids) { |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return List.of(); |
| | | } |
| | | return ticketMapper.selectBatchIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public PageResult<AfterSaleTicketDO> getTicketPage(AfterSaleTicketPageReqVO pageReqVO, Long userId) { |
| | | return ticketMapper.selectPage(pageReqVO, userId, pageReqVO.getSceneType(), |
| | | pageReqVO.getNo(), pageReqVO.getName(), |
| | | pageReqVO.getCustomerId(), pageReqVO.getSaleOrderId(), |
| | | pageReqVO.getStatus(), pageReqVO.getIssueType()); |
| | | } |
| | | |
| | | @Override |
| | | public List<AfterSaleTicketItemDO> getTicketItemListByTicketId(Long ticketId) { |
| | | return ticketItemMapper.selectListByTicketId(ticketId); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void assignTicket(Long id, Long handlerUserId) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.DRAFT, AfterSaleTicketStatusEnum.PROCESSING); |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(id).setHandlerUserId(handlerUserId) |
| | | .setStatus(AfterSaleTicketStatusEnum.PROCESSING.getStatus())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void classifyTicket(Long id, Integer issueType, String issueCategory, Integer severityLevel) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.PROCESSING); |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(id) |
| | | .setIssueType(issueType).setIssueCategory(issueCategory).setSeverityLevel(severityLevel)); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void resolveTicket(Long id) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.PROCESSING, |
| | | AfterSaleTicketStatusEnum.WAITING_RETURN, AfterSaleTicketStatusEnum.WAITING_REFUND); |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(id) |
| | | .setStatus(AfterSaleTicketStatusEnum.COMPLETED.getStatus()) |
| | | .setResolvedTime(LocalDateTime.now())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void closeTicket(Long id) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.COMPLETED); |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(id) |
| | | .setStatus(AfterSaleTicketStatusEnum.CLOSED.getStatus()) |
| | | .setClosedTime(LocalDateTime.now())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void cancelTicket(Long id) { |
| | | AfterSaleTicketDO ticket = validateTicketExists(id); |
| | | validateTicketStatus(ticket, AfterSaleTicketStatusEnum.DRAFT, AfterSaleTicketStatusEnum.PROCESSING); |
| | | ticketMapper.updateById(new AfterSaleTicketDO().setId(id) |
| | | .setStatus(AfterSaleTicketStatusEnum.CANCELED.getStatus())); |
| | | } |
| | | |
| | | // ========== å
鍿¹æ³ ========== |
| | | |
| | | private AfterSaleTicketDO validateTicketExists(Long id) { |
| | | AfterSaleTicketDO ticket = ticketMapper.selectById(id); |
| | | if (ticket == null) { |
| | | throw exception(TICKET_NOT_EXISTS); |
| | | } |
| | | return ticket; |
| | | } |
| | | |
| | | private void validateTicketStatus(AfterSaleTicketDO ticket, AfterSaleTicketStatusEnum... allowedStatuses) { |
| | | for (AfterSaleTicketStatusEnum status : allowedStatuses) { |
| | | if (status.getStatus().equals(ticket.getStatus())) { |
| | | return; |
| | | } |
| | | } |
| | | throw exception(TICKET_STATUS_ERROR); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.aftersales.util; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.extra.spring.SpringUtil; |
| | | import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; |
| | | import cn.iocoder.yudao.module.aftersales.dal.dataobject.permission.AfterSalePermissionDO; |
| | | import cn.iocoder.yudao.module.aftersales.enums.AfterSaleBizTypeEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum; |
| | | import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSaleSceneTypeEnum; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| | | import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; |
| | | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| | | import org.springframework.util.Assert; |
| | | |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | |
| | | /** |
| | | * å®åæ¨¡åæ°æ®æéå·¥å
·ç±» |
| | | */ |
| | | public class AfterSalePermissionUtils { |
| | | |
| | | /** |
| | | * æ ¡éªç¨æ·æ¯å¦æ¯å®å管çå |
| | | * |
| | | * @return æ¯/å¦ |
| | | */ |
| | | public static boolean isAftersaleAdmin() { |
| | | PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class); |
| | | return permissionApi.hasAnyRoles(getLoginUserId(), "aftersales_admin"); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªç¨æ·æ¯å¦ææ¥çå
¨é¨å®åæ°æ®çæé |
| | | */ |
| | | private static boolean hasViewAllPermission() { |
| | | PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class); |
| | | return permissionApi.hasAnyPermissions(getLoginUserId(), "aftersales:view-all"); |
| | | } |
| | | |
| | | /** |
| | | * æé å®åæ¨¡åæ°æ®ãåé¡µãæ¥è¯¢æ¡ä»¶ |
| | | * |
| | | * @param query è¿è¡¨æ¥è¯¢å¯¹è±¡ |
| | | * @param bizType æ°æ®ç±»å {@link AfterSaleBizTypeEnum} |
| | | * @param bizId æ°æ®ç¼å· |
| | | * @param userId ç¨æ·ç¼å· |
| | | * @param sceneType åºæ¯ç±»å |
| | | */ |
| | | public static <T extends MPJLambdaWrapper<?>, S> void appendPermissionCondition(T query, Integer bizType, |
| | | SFunction<S, ?> bizId, |
| | | Long userId, Integer sceneType) { |
| | | MybatisPlusJoinProperties mybatisPlusJoinProperties = SpringUtil.getBean(MybatisPlusJoinProperties.class); |
| | | final String ownerUserIdField = mybatisPlusJoinProperties.getTableAlias() + ".owner_user_id"; |
| | | // åºæ¯ä¸ï¼æè´è´£çæ°æ® |
| | | if (AfterSaleSceneTypeEnum.isOwner(sceneType)) { |
| | | query.eq(ownerUserIdField, userId); |
| | | } |
| | | // åºæ¯äºï¼æåä¸çæ°æ®ï¼ææè¯»æåæéï¼å¹¶ä¸ä¸æ¯è´è´£äººï¼ |
| | | if (AfterSaleSceneTypeEnum.isInvolved(sceneType)) { |
| | | if (isAftersaleAdmin()) { |
| | | return; |
| | | } |
| | | query.innerJoin(AfterSalePermissionDO.class, on -> on.eq(AfterSalePermissionDO::getBizType, bizType) |
| | | .eq(AfterSalePermissionDO::getBizId, bizId) |
| | | .in(AfterSalePermissionDO::getLevel, AfterSalePermissionLevelEnum.READ.getLevel(), |
| | | AfterSalePermissionLevelEnum.WRITE.getLevel()) |
| | | .eq(AfterSalePermissionDO::getUserId, userId)); |
| | | query.ne(ownerUserIdField, userId); |
| | | } |
| | | // åºæ¯ä¸ï¼ä¸å±è´è´£çæ°æ®ï¼ä¸å±æ¯è´è´£äººï¼ |
| | | if (AfterSaleSceneTypeEnum.isSubordinate(sceneType)) { |
| | | AdminUserApi adminUserApi = SpringUtil.getBean(AdminUserApi.class); |
| | | List<AdminUserRespDTO> subordinateUsers = adminUserApi.getUserListBySubordinate(userId); |
| | | if (CollUtil.isEmpty(subordinateUsers)) { |
| | | query.eq(ownerUserIdField, -1); |
| | | } else { |
| | | query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); |
| | | } |
| | | } |
| | | // åºæ¯åï¼å
¨é¨æ°æ®ï¼éè¦æ view-all æéæå®å管çåï¼ |
| | | if (AfterSaleSceneTypeEnum.isAll(sceneType)) { |
| | | if (isAftersaleAdmin() || hasViewAllPermission()) { |
| | | return; |
| | | } |
| | | query.eq(ownerUserIdField, userId); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | |
| | | private BigDecimal taxPrice; |
| | | |
| | | @Schema(description = "éæ±æ¥æ") |
| | | private LocalDateTime demandTime; |
| | | private LocalDate demandTime; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | private String remark; |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | |
| | | private BigDecimal taxPercent; |
| | | |
| | | @Schema(description = "éæ±æ¥æ") |
| | | private LocalDateTime demandTime; |
| | | private LocalDate demandTime; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | private String remark; |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; |
| | | import cn.iocoder.yudao.module.mes.api.productsales.MesWmProductSalesLineApi; |
| | | import cn.iocoder.yudao.module.mes.api.salesnotice.MesWmSalesNoticeApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private MesWmSalesNoticeApi salesNoticeApi; |
| | | @Resource |
| | | private MesWmProductSalesLineApi productSalesLineApi; |
| | | @Resource |
| | | private MesProMpsApi mpsApi; |
| | | @Resource |
| | |
| | | List<ErpSaleOrderItemDO> saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderId(id); |
| | | Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( |
| | | convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); |
| | | Map<Long, String> batchCodeMap = productSalesLineApi.getBatchCodesBySaleOrderItemIds( |
| | | convertSet(saleOrderItemList, ErpSaleOrderItemDO::getId)); |
| | | return success(BeanUtils.toBean(saleOrder, ErpSaleOrderRespVO.class, saleOrderVO -> |
| | | saleOrderVO.setItems(BeanUtils.toBean(saleOrderItemList, ErpSaleOrderRespVO.Item.class, item -> { |
| | | // åºåä¿¡æ¯æä¸æ¥è¯¢ï¼ä»å¨ç©æµæ¨¡åï¼ |
| | | item.setStockCount(BigDecimal.ZERO); |
| | | item.setBatchCode(batchCodeMap.get(item.getId())); |
| | | MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())); |
| | | })).setAttachmentList(storageAttachmentApi.listAttachments("erp_sale_order", id)))); |
| | |
| | | // 1.5 åè´§éç¥åä¿¡æ¯ |
| | | Map<Long, Boolean> salesNoticeMap = salesNoticeApi.checkSalesNoticeBySaleOrderIds( |
| | | convertSet(pageResult.getList(), ErpSaleOrderDO::getId)); |
| | | // 1.6 æ£æ¥æ¯å¦å¯ä»¥çæåè´§éç¥åï¼éè¦ç产çæç»å¯¹åºç MPS æ¯å¦å·²å®æï¼ |
| | | // 1.6 åºåºæ¹å· |
| | | Map<Long, String> batchCodeMap = productSalesLineApi.getBatchCodesBySaleOrderItemIds( |
| | | convertSet(saleOrderItemList, ErpSaleOrderItemDO::getId)); |
| | | // 1.7 æ£æ¥æ¯å¦å¯ä»¥çæåè´§éç¥åï¼éè¦ç产çæç»å¯¹åºç MPS æ¯å¦å·²å®æï¼ |
| | | // çéåºéè¦ç产çæç»ID |
| | | List<Long> needProductionItemIds = saleOrderItemList.stream() |
| | | .filter(item -> item.getNeedProduction() != null && item.getNeedProduction() == 1) |
| | |
| | | // 2. å¼å§æ¼æ¥ |
| | | return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> { |
| | | saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class, |
| | | item -> MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())))); |
| | | item -> { |
| | | item.setBatchCode(batchCodeMap.get(item.getId())); |
| | | MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())); |
| | | })); |
| | | saleOrder.setProductNames(CollUtil.join(saleOrder.getItems(), "ï¼", ErpSaleOrderRespVO.Item::getProductName)); |
| | | MapUtils.findAndThen(customerMap, saleOrder.getCustomerId(), supplier -> saleOrder.setCustomerName(supplier.getName())); |
| | | MapUtils.findAndThen(userMap, Long.parseLong(saleOrder.getCreator()), user -> saleOrder.setCreatorName(user.getNickname())); |
| | |
| | | @Schema(description = "éå®ç¶æ", example = "2") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "åºåºç¶æ", example = "3") |
| | | private Integer outStatus; |
| | | |
| | | @Schema(description = "çäº§ç¶æ", example = "0") |
| | | private Integer productionStatus; |
| | | |
| | | @Schema(description = "æ¯å¦éè¦ç产", example = "1") |
| | | private Integer needProduction; |
| | | |
| | | @Schema(description = "å建è
") |
| | | private String creator; |
| | | |
| | |
| | | @Schema(description = "å
³èç MPS ç¼å·", example = "1024") |
| | | private Long mpsId; |
| | | |
| | | // ========== åºåºæ¹å· ========== |
| | | |
| | | @Schema(description = "åºåºæ¹å·", example = "B2026001ãB2026002") |
| | | private String batchCode; |
| | | |
| | | // ========== å
³èåæ®µ ========== |
| | | |
| | | @Schema(description = "产ååç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å·§å
å") |
| | |
| | | import lombok.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * ERP éè´ç³è¯·æç» DO |
| | |
| | | /** |
| | | * éæ±æ¥æ |
| | | */ |
| | | private LocalDateTime demandTime; |
| | | private LocalDate demandTime; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | |
| | | .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) |
| | | .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) |
| | | .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) |
| | | .eqIfPresent(ErpSaleOrderDO::getOutStatus, reqVO.getOutStatus()) |
| | | .eqIfPresent(ErpSaleOrderDO::getProductionStatus, reqVO.getProductionStatus()) |
| | | .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark()) |
| | | .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) |
| | | .orderByDesc(ErpSaleOrderDO::getId); |
| | | if (reqVO.getProductId() != null) { |
| | | if (reqVO.getProductId() != null || reqVO.getNeedProduction() != null) { |
| | | query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) |
| | | .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) |
| | | .eq(reqVO.getNeedProduction() != null, ErpSaleOrderItemDO::getNeedProduction, reqVO.getNeedProduction()) |
| | | .groupBy(ErpSaleOrderDO::getId); // é¿å
1 坹夿¥è¯¢ï¼äº§çç¸åç 1 |
| | | } |
| | | return selectJoinPage(reqVO, ErpSaleOrderDO.class, query); |
| | |
| | | .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) |
| | | .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) |
| | | .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) |
| | | .eqIfPresent(ErpSaleOrderDO::getOutStatus, reqVO.getOutStatus()) |
| | | .eqIfPresent(ErpSaleOrderDO::getProductionStatus, reqVO.getProductionStatus()) |
| | | .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark()) |
| | | .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) |
| | | .orderByDesc(ErpSaleOrderDO::getId); |
| | |
| | | } |
| | | query.in(ErpSaleOrderDO::getCustomerId, permittedCustomerIds); |
| | | } |
| | | if (reqVO.getProductId() != null) { |
| | | if (reqVO.getProductId() != null || reqVO.getNeedProduction() != null) { |
| | | query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) |
| | | .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) |
| | | .eq(reqVO.getNeedProduction() != null, ErpSaleOrderItemDO::getNeedProduction, reqVO.getNeedProduction()) |
| | | .groupBy(ErpSaleOrderDO::getId); // é¿å
1 坹夿¥è¯¢ï¼äº§çç¸åç 1 |
| | | } |
| | | return selectJoinPage(reqVO, ErpSaleOrderDO.class, query); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.api.productsales; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * MES éå®åºåºåè¡ API æ¥å£ |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | public interface MesWmProductSalesLineApi { |
| | | |
| | | /** |
| | | * æ ¹æ®éå®è®¢åæç» ID å表æ¥è¯¢åºåºæ¹å· |
| | | * |
| | | * @param saleOrderItemIds éå®è®¢åæç» ID å表 |
| | | * @return Map<éå®è®¢åæç»ID, æ¹å·ä¸²èå符串> |
| | | */ |
| | | Map<Long, String> getBatchCodesBySaleOrderItemIds(Collection<Long> saleOrderItemIds); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.api.returnsales; |
| | | |
| | | import cn.iocoder.yudao.module.mes.api.returnsales.dto.MesWmReturnSalesCreateReqDTO; |
| | | |
| | | /** |
| | | * MES éå®éè´§å API æ¥å£ |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | public interface MesWmReturnSalesApi { |
| | | |
| | | /** |
| | | * å建éå®éè´§åï¼ç±å®å模åè°ç¨ï¼ |
| | | * |
| | | * @param reqDTO å建请æ±åæ° |
| | | * @return å建çéå®éè´§åç¼å· |
| | | */ |
| | | Long createReturnSales(MesWmReturnSalesCreateReqDTO reqDTO); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.api.returnsales.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * MES éå®éè´§åå建 Request DTO |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | @Schema(description = "RPC æå¡ - MES éå®éè´§åå建 Request DTO") |
| | | @Data |
| | | public class MesWmReturnSalesCreateReqDTO { |
| | | |
| | | @Schema(description = "éè´§åç¼å·", requiredMode = Schema.RequiredMode.REQUIRED, example = "RS202603010001") |
| | | private String code; |
| | | |
| | | @Schema(description = "éè´§ååç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "å®åéè´§") |
| | | private String name; |
| | | |
| | | @Schema(description = "éå®è®¢å ID", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "SO202603010001") |
| | | private String salesOrderCode; |
| | | |
| | | @Schema(description = "å®¢æ· ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | private Long clientId; |
| | | |
| | | @Schema(description = "éè´§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private LocalDate returnDate; |
| | | |
| | | @Schema(description = "éè´§åå ", requiredMode = Schema.RequiredMode.REQUIRED, example = "è´¨éé®é¢") |
| | | private String returnReason; |
| | | |
| | | @Schema(description = "夿³¨", example = "å®åéè´§ç³è¯·å
³è") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å®åéè´§ç³è¯·ç¼å·ï¼å
³è after_sale_return.idï¼", example = "1") |
| | | private Long afterSaleReturnId; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.api.productsales; |
| | | |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * MES éå®åºåºåè¡ API å®ç°ç±» |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | @Service |
| | | @Validated |
| | | public class MesWmProductSalesLineApiImpl implements MesWmProductSalesLineApi { |
| | | |
| | | @Resource |
| | | private MesWmProductSalesLineMapper productSalesLineMapper; |
| | | |
| | | @Override |
| | | public Map<Long, String> getBatchCodesBySaleOrderItemIds(Collection<Long> saleOrderItemIds) { |
| | | return productSalesLineMapper.selectBatchCodesBySaleOrderItemIds(saleOrderItemIds); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.mes.api.returnsales; |
| | | |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.api.returnsales.dto.MesWmReturnSalesCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * MES éå®éè´§å API å®ç°ç±» |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | @Service |
| | | public class MesWmReturnSalesApiImpl implements MesWmReturnSalesApi { |
| | | |
| | | @Resource |
| | | private MesWmReturnSalesService returnSalesService; |
| | | |
| | | @Override |
| | | public Long createReturnSales(MesWmReturnSalesCreateReqDTO reqDTO) { |
| | | MesWmReturnSalesSaveReqVO createReqVO = BeanUtils.toBean(reqDTO, MesWmReturnSalesSaveReqVO.class); |
| | | return returnSalesService.createReturnSales(createReqVO); |
| | | } |
| | | |
| | | } |
| | |
| | | import lombok.EqualsAndHashCode; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| | | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; |
| | | |
| | | /** |
| | | * 管çåå° - MES éå®éè´§ç¸å
³ |
| | |
| | | @Schema(description = "éè´§ååç§°", example = "éå®éè´§") |
| | | private String name; |
| | | |
| | | @Schema(description = "éå®è®¢å ID", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "SO202603010001") |
| | | private String salesOrderCode; |
| | | |
| | |
| | | private Integer status; |
| | | |
| | | @Schema(description = "éè´§æ¥æ") |
| | | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| | | private LocalDateTime[] returnDate; |
| | | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) |
| | | private LocalDate[] returnDate; |
| | | |
| | | } |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | |
| | | @Schema(description = "éè´§ååç§°", requiredMode = Schema.RequiredMode.REQUIRED, example = "éå®éè´§") |
| | | private String name; |
| | | |
| | | @Schema(description = "éå®è®¢å ID", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "SO202603010001") |
| | | private String salesOrderCode; |
| | | |
| | |
| | | private String clientName; |
| | | |
| | | @Schema(description = "éè´§æ¥æ") |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | |
| | | @Schema(description = "éè´§åå ", example = "è´¨éé®é¢") |
| | | private String returnReason; |
| | |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * 管çåå° - MES éå®éè´§åæ°å¢/ä¿®æ¹ Request VO |
| | |
| | | @NotBlank(message = "éè´§ååç§°ä¸è½ä¸ºç©º") |
| | | private String name; |
| | | |
| | | @Schema(description = "éå®è®¢å ID", example = "1") |
| | | private Long saleOrderId; |
| | | |
| | | @Schema(description = "éå®è®¢åç¼å·", example = "SO202603010001") |
| | | private String salesOrderCode; |
| | | |
| | |
| | | |
| | | @Schema(description = "éè´§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "éè´§æ¥æä¸è½ä¸ºç©º") |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | |
| | | @Schema(description = "éè´§åå ", requiredMode = Schema.RequiredMode.REQUIRED, example = "è´¨éé®é¢") |
| | | @NotBlank(message = "éè´§åå ä¸è½ä¸ºç©º") |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "管çåå° - MES ä¾åºåéè´§å Response VO") |
| | |
| | | private String vendorNickname; |
| | | |
| | | @Schema(description = "éè´§æ¥æ") |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | |
| | | @Schema(description = "éè´§åå ", example = "è´¨éä¸åæ ¼") |
| | | private String returnReason; |
| | |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | |
| | | @Schema(description = "管çåå° - MES ä¾åºåéè´§åæ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | |
| | | @Schema(description = "éè´§æ¥æ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull(message = "éè´§æ¥æä¸è½ä¸ºç©º") |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | |
| | | @Schema(description = "éè´§åå ", example = "è´¨éä¸åæ ¼") |
| | | private String returnReason; |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; |
| | | |
| | | /** |
| | |
| | | */ |
| | | private String name; |
| | | /** |
| | | * éå®è®¢å ID |
| | | */ |
| | | private Long saleOrderId; |
| | | /** |
| | | * éå®è®¢åç¼å· |
| | | */ |
| | | private String salesOrderCode; |
| | |
| | | /** |
| | | * éè´§æ¥æ |
| | | */ |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | /** |
| | | * éè´§åå |
| | | */ |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.*; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalDate; |
| | | import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; |
| | | |
| | | /** |
| | |
| | | /** |
| | | * éè´§æ¥æ |
| | | */ |
| | | private LocalDateTime returnDate; |
| | | private LocalDate returnDate; |
| | | /** |
| | | * éè´§åå |
| | | */ |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales; |
| | | |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * MES éå®åºåºåè¡ Mapper |
| | |
| | | .orderByDesc(MesWmProductSalesLineDO::getId)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®éå®è®¢åæç» ID å表æ¥è¯¢åºåºè¡ï¼æ saleOrderItemId åç»è¿åæ¹å· |
| | | */ |
| | | default Map<Long, String> selectBatchCodesBySaleOrderItemIds(java.util.Collection<Long> saleOrderItemIds) { |
| | | if (saleOrderItemIds == null || saleOrderItemIds.isEmpty()) { |
| | | return java.util.Collections.emptyMap(); |
| | | } |
| | | List<MesWmProductSalesLineDO> lines = selectList(new LambdaQueryWrapperX<MesWmProductSalesLineDO>() |
| | | .in(MesWmProductSalesLineDO::getSaleOrderItemId, saleOrderItemIds)); |
| | | return lines.stream() |
| | | .filter(l -> l.getBatchCode() != null && !l.getBatchCode().isEmpty()) |
| | | .collect(java.util.stream.Collectors.groupingBy( |
| | | MesWmProductSalesLineDO::getSaleOrderItemId, |
| | | java.util.LinkedHashMap::new, |
| | | java.util.stream.Collectors.collectingAndThen( |
| | | java.util.stream.Collectors.mapping(MesWmProductSalesLineDO::getBatchCode, |
| | | java.util.stream.Collectors.toSet()), |
| | | codes -> String.join("ã", codes)))); |
| | | } |
| | | |
| | | default void updateQualityStatusByIds(List<Long> ids, Integer qualityStatus) { |
| | | update(new MesWmProductSalesLineDO().setQualityStatus(qualityStatus), |
| | | new LambdaUpdateWrapper<MesWmProductSalesLineDO>().in(MesWmProductSalesLineDO::getId, ids)); |
| | |
| | | HRM_RESIGNATION_APPLICATION("hrm_resignation_application", "HRM 离èç³è¯·"), |
| | | HRM_ATTENDANCE_EXCEPTION("hrm_attendance_exception", "HRM èå¤å¼å¸¸"), |
| | | |
| | | // ===== å®å ===== |
| | | AFTER_SALE_TICKET("aftersales_ticket", "å®åå·¥å"), |
| | | AFTER_SALE_RETURN("aftersales_return", "å®åéè´§ç³è¯·"), |
| | | |
| | | // ===== MES ===== |
| | | MES_PD_DOCUMENT("mes_pd_document", "MES è®¾è®¡èµæ"); |
| | | |
| | |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- å®åå·¥åç®¡çæ¨¡å --> |
| | | <dependency> |
| | | <groupId>cn.iocoder.boot</groupId> |
| | | <artifactId>yudao-module-aftersales</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- spring boot é
ç½®æéä¾èµ --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |