Merge remote-tracking branch 'origin/dev_New_pro' into dev_New_pro
# Conflicts:
# src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
已添加52个文件
已重命名11个文件
已修改124个文件
已删除1个文件
| | |
| | | .gradle
|
| | | /build/
|
| | | !gradle/wrapper/gradle-wrapper.jar
|
| | |
|
| | | claude.md
|
| | | target/
|
| | | !.mvn/wrapper/maven-wrapper.jar
|
| | |
|
| | |
| | |
|
| | | !*/build/*.java
|
| | | !*/build/*.html
|
| | | !*/build/*.xml |
| | | !*/build/*.xml
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # AccountSubject æ å½¢æ¹é åç«¯ä¿®æ¹ææ¡£ |
| | | |
| | | æ´æ°æ¶é´ï¼2026-05-12 |
| | | |
| | | ## 1. åæ´èæ¯ |
| | | |
| | | `AccountSubjectController` å·²æ¹ä¸ºç¶åå±çº§é彿¨¡å¼ï¼`/accountSubject/list` ç°å¨è¿åæ å½¢ç»æï¼`children` éå½ï¼ï¼ä¸åæ¯å纯çå¹³éºå表ã |
| | | |
| | | --- |
| | | |
| | | ## 2. å端æ¥å£åå |
| | | |
| | | ### 2.1 æ¥è¯¢æ¥å£ï¼å·²åæ´ä¸ºæ ï¼ |
| | | |
| | | - URLï¼`GET /accountSubject/list` |
| | | - å
¥åï¼ä¿æä¸åï¼`current,size,subjectCode,subjectName,subjectType,status`ï¼ |
| | | - åºåï¼ä»æ¯å页壳ï¼`records,total`ï¼ï¼ä½ `records` å为æ èç¹æ°ç»ï¼æ ¹èç¹å页ï¼åèç¹éå½å
åµï¼ |
| | | |
| | | 示ä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "æä½æå", |
| | | "data": { |
| | | "records": [ |
| | | { |
| | | "id": 1, |
| | | "parentId": null, |
| | | "subjectCode": "1002", |
| | | "subjectName": "é¶è¡å款", |
| | | "subjectType": "èµäº§ç±»", |
| | | "balanceDirection": "åæ¹", |
| | | "status": 0, |
| | | "leaf": false, |
| | | "children": [ |
| | | { |
| | | "id": 2, |
| | | "parentId": 1, |
| | | "subjectCode": "100201", |
| | | "subjectName": "å·¥è¡å款", |
| | | "subjectType": "èµäº§ç±»", |
| | | "balanceDirection": "åæ¹", |
| | | "status": 0, |
| | | "leaf": true, |
| | | "children": [] |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "total": 1 |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 2.2 æ°å¢/ç¼è¾æ¥å£å段åå |
| | | |
| | | - `POST /accountSubject/add` |
| | | - `PUT /accountSubject/edit` |
| | | |
| | | æ°å¢æ¯æåæ®µï¼ |
| | | |
| | | - `parentId`ï¼ç¶èç¹IDï¼ä¸ºç©ºè¡¨ç¤ºæ ¹èç¹ï¼ |
| | | |
| | | 示ä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "id": 2, |
| | | "parentId": 1, |
| | | "subjectCode": "100201", |
| | | "subjectName": "å·¥è¡å款", |
| | | "subjectType": "èµäº§ç±»", |
| | | "balanceDirection": "åæ¹", |
| | | "status": 0, |
| | | "remark": "" |
| | | } |
| | | ``` |
| | | |
| | | ### 2.3 å 餿¥å£è¡ä¸ºåå |
| | | |
| | | - `DELETE /accountSubject/remove/{ids}` |
| | | |
| | | è¡ä¸ºï¼ |
| | | |
| | | 1. å é¤ç¶èç¹æ¶ä¼éå½å 餿æååèç¹ã |
| | | 2. è¥ä»»æå¾
å é¤èç¹ï¼å«ååï¼å·²è¢« `fin_voucher_entry.subject_code` å¼ç¨ï¼åæ´ä½å é¤å¤±è´¥ã |
| | | |
| | | --- |
| | | |
| | | ## 3. å端æ¹é æ¸
å |
| | | |
| | | ## 3.1 æ»è´¦ç§ç®ç®¡ç页 |
| | | |
| | | æä»¶ï¼`src/views/financialManagement/generalLedger/index.vue` |
| | | |
| | | ### å¿
æ¹é¡¹ |
| | | |
| | | 1. æ°å¢âç¶ç§ç®âéæ©æ§ä»¶ï¼`el-cascader` æ `el-tree-select`ï¼ï¼ä¿åæ¶å¸¦ `parentId`ã |
| | | 2. å表æ¹ä¸ºæ 表å±ç¤ºï¼æ¨è `el-table` + `row-key` + `tree-props`ï¼ã |
| | | 3. æç´¢é»è¾ä¿æä¸åï¼ä½è¦å
¼å®¹ `records` 为æ ç»æã |
| | | |
| | | --- |
| | | |
| | | ## 3.2 åè¯é¡µç§ç®ä¸æ |
| | | |
| | | æä»¶ï¼`src/views/financialManagement/voucher/index.vue` |
| | | |
| | | å½ååè¯åå½ä½¿ç¨ `el-select`ï¼å¹³éºï¼ã |
| | | å端已è¿åæ ï¼éè¦å端æå¹³åååç»å®ä¸æã |
| | | |
| | | 示ä¾ï¼å¯å¤ç¨ï¼ï¼ |
| | | |
| | | ```js |
| | | const flattenSubjectTree = (nodes, result = []) => { |
| | | (nodes || []).forEach(node => { |
| | | result.push({ |
| | | code: node.subjectCode, |
| | | name: node.subjectName, |
| | | id: node.id, |
| | | parentId: node.parentId |
| | | }); |
| | | if (node.children?.length) { |
| | | flattenSubjectTree(node.children, result); |
| | | } |
| | | }); |
| | | return result; |
| | | }; |
| | | |
| | | // list æ¥å£è¿ååï¼ |
| | | const treeRecords = response.data?.records || []; |
| | | subjectList.value = flattenSubjectTree(treeRecords); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## 3.3 ç§ç®æ»è´¦/æç»è´¦é¡µçº§è |
| | | |
| | | æä»¶ï¼ |
| | | |
| | | - `src/views/financialManagement/voucher/generalLedger.vue` |
| | | - `src/views/financialManagement/voucher/detailLedger.vue` |
| | | |
| | | å½åé»è¾æ¯æ `records` å¼ºå¶æ å°æ `children: []`ï¼éè¦å é¤è¿æ®µâå¹³éºæ¹é âï¼ç´æ¥ä½¿ç¨å端æ ã |
| | | |
| | | 示ä¾ï¼å¯å¤ç¨ï¼ï¼ |
| | | |
| | | ```js |
| | | const toCascaderTree = (nodes = []) => |
| | | nodes |
| | | .filter(item => item.subjectCode && item.subjectName) |
| | | .map(item => ({ |
| | | code: item.subjectCode, |
| | | name: item.subjectName, |
| | | children: toCascaderTree(item.children || []) |
| | | })); |
| | | |
| | | subjectOptions.value = toCascaderTree(response.data?.records || []); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## 4. 建议çåç«¯åæ®µçº¦å® |
| | | |
| | | 建议å¨å端 `form` å¢å ï¼ |
| | | |
| | | - `parentId: null` |
| | | |
| | | å¹¶å¨ç¼è¾åå¡«æ¶ä¿æ `parentId`ã |
| | | |
| | | --- |
| | | |
| | | ## 5. èè°æ³¨æäºé¡¹ |
| | | |
| | | 1. `/accountSubject/list` ç `total` æ¯æ ¹èç¹æ°éï¼ä¸æ¯å
¨éèç¹æ°ã |
| | | 2. è¥é¡µé¢ä»æå¹³éº `records.map(...)` å¤çï¼ä¼ä¸¢å¤±åèç¹ã |
| | | 3. å é¤ç§ç®å¤±è´¥æ¶ï¼ä¼å
æ£æ¥æ¯å¦è¢«åè¯åå½å¼ç¨ã |
| | | 4. ä¿å失败åºç°âç¶ç§ç®ä¸è½æ¯å½åç§ç®æå
¶åç§ç®âæ¶ï¼éè¦å端éå¶ç¶èç¹å¯éèå´ã |
| | | |
| | | --- |
| | | |
| | | ## 6. æ°æ®åºåæ®µè¦æ± |
| | | |
| | | `account_subject` éè¦å
å« `parent_id` åæ®µï¼`bigint`ï¼å¯ç©ºï¼ã |
| | | è¥çº¿ä¸åºå°æªæ·»å ï¼è¯·å
æ§è¡ DDL åèè°ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- account_subject å¢å ç¶çº§ç§ç®åæ®µï¼æ å½¢ç»æï¼ |
| | | ALTER TABLE `account_subject` |
| | | ADD COLUMN `parent_id` bigint NULL COMMENT 'ç¶ç§ç®IDï¼ä¸ºç©ºè¡¨ç¤ºæ ¹èç¹ï¼' AFTER `id`; |
| | | |
| | | CREATE INDEX `idx_account_subject_parent_id` ON `account_subject` (`parent_id`); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- è´¢å¡ç®¡ç模åå»ºè¡¨èæ¬ï¼åºå®èµäº§/æ å½¢èµäº§/åè¯/ç§ç®è´¦ï¼ |
| | | -- 说æï¼ |
| | | -- 1) æ»è´¦ç§ç®ç»§ç»å¤ç¨å·²æè¡¨ account_subjectï¼ä¸éå¤å建 fin_account_subjectã |
| | | -- 2) éé¢å段ç»ä¸ decimal(18,2)ã |
| | | |
| | | CREATE TABLE IF NOT EXISTS `fin_fixed_asset` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', |
| | | `asset_code` varchar(64) NOT NULL COMMENT 'èµäº§ç¼å·', |
| | | `asset_name` varchar(128) NOT NULL COMMENT 'èµäº§åç§°', |
| | | `category` varchar(64) NOT NULL COMMENT 'èµäº§ç±»å«', |
| | | `specification` varchar(255) DEFAULT NULL COMMENT 'è§æ ¼åå·', |
| | | `purchase_date` date NOT NULL COMMENT 'è´ç½®æ¥æ', |
| | | `original_value` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'èµäº§åå¼', |
| | | `useful_life` int NOT NULL DEFAULT '1' COMMENT '使ç¨å¹´é(å¹´)', |
| | | `residual_rate` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'æ®å¼ç(%)', |
| | | `accumulated_depreciation` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'ç´¯è®¡ææ§', |
| | | `net_value` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'åå¼', |
| | | `location` varchar(255) DEFAULT NULL COMMENT 'åæ¾å°ç¹', |
| | | `department` varchar(128) DEFAULT NULL COMMENT '使ç¨é¨é¨', |
| | | `keeper` varchar(64) DEFAULT NULL COMMENT 'ä¿ç®¡äºº', |
| | | `status` varchar(32) NOT NULL DEFAULT 'in_use' COMMENT 'ç¶æ: in_use/idle/repair/scrapped', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `create_user` varchar(64) DEFAULT NULL COMMENT 'å建人', |
| | | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_user` varchar(64) DEFAULT NULL COMMENT 'ä¿®æ¹äºº', |
| | | `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | | `dept_id` bigint DEFAULT NULL COMMENT 'é¨é¨ID', |
| | | PRIMARY KEY (`id`), |
| | | UNIQUE KEY `uk_fin_fixed_asset_code` (`asset_code`), |
| | | KEY `idx_fin_fixed_asset_status` (`status`), |
| | | KEY `idx_fin_fixed_asset_category` (`category`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='åºå®èµäº§'; |
| | | |
| | | CREATE TABLE IF NOT EXISTS `fin_intangible_asset` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', |
| | | `asset_code` varchar(64) NOT NULL COMMENT 'èµäº§ç¼å·', |
| | | `asset_name` varchar(128) NOT NULL COMMENT 'èµäº§åç§°', |
| | | `category` varchar(64) NOT NULL COMMENT 'èµäº§ç±»å«', |
| | | `certificate_no` varchar(128) DEFAULT NULL COMMENT 'è¯ä¹¦ç¼å·', |
| | | `acquisition_date` date NOT NULL COMMENT 'å徿¥æ', |
| | | `original_value` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'èµäº§åå¼', |
| | | `amortization_period` int NOT NULL DEFAULT '1' COMMENT 'æéå¹´é(å¹´)', |
| | | `residual_rate` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'æ®å¼ç(%)', |
| | | `accumulated_amortization` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT '累计æé', |
| | | `net_value` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'åå¼', |
| | | `validity_date` date DEFAULT NULL COMMENT 'æææè³', |
| | | `status` varchar(32) NOT NULL DEFAULT 'in_use' COMMENT 'ç¶æ: in_use/expired/amortized', |
| | | `description` varchar(1000) DEFAULT NULL COMMENT 'èµäº§æè¿°', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `create_user` varchar(64) DEFAULT NULL COMMENT 'å建人', |
| | | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_user` varchar(64) DEFAULT NULL COMMENT 'ä¿®æ¹äºº', |
| | | `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | | `dept_id` bigint DEFAULT NULL COMMENT 'é¨é¨ID', |
| | | PRIMARY KEY (`id`), |
| | | UNIQUE KEY `uk_fin_intangible_asset_code` (`asset_code`), |
| | | KEY `idx_fin_intangible_asset_status` (`status`), |
| | | KEY `idx_fin_intangible_asset_category` (`category`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='æ å½¢èµäº§'; |
| | | |
| | | CREATE TABLE IF NOT EXISTS `fin_voucher` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', |
| | | `voucher_no` varchar(64) NOT NULL COMMENT 'åè¯åå·', |
| | | `voucher_date` date NOT NULL COMMENT 'åè¯æ¥æ', |
| | | `summary` varchar(500) DEFAULT NULL COMMENT 'æè¦', |
| | | `debit` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'åæ¹å计', |
| | | `credit` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'è´·æ¹å计', |
| | | `creator` varchar(64) DEFAULT NULL COMMENT 'å¶å人', |
| | | `status` varchar(32) NOT NULL DEFAULT 'unposted' COMMENT 'ç¶æ: unposted/posted/cancelled', |
| | | `attachment_count` int NOT NULL DEFAULT '0' COMMENT 'éä»¶å¼ æ°', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `create_user` varchar(64) DEFAULT NULL COMMENT 'å建人', |
| | | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_user` varchar(64) DEFAULT NULL COMMENT 'ä¿®æ¹äºº', |
| | | `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | | `dept_id` bigint DEFAULT NULL COMMENT 'é¨é¨ID', |
| | | PRIMARY KEY (`id`), |
| | | UNIQUE KEY `uk_fin_voucher_no` (`voucher_no`), |
| | | KEY `idx_fin_voucher_date` (`voucher_date`), |
| | | KEY `idx_fin_voucher_status` (`status`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='åè¯ä¸»è¡¨'; |
| | | |
| | | CREATE TABLE IF NOT EXISTS `fin_voucher_entry` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', |
| | | `voucher_id` bigint NOT NULL COMMENT 'åè¯ID', |
| | | `row_no` int NOT NULL DEFAULT '1' COMMENT 'è¡å·', |
| | | `subject_code` varchar(64) NOT NULL COMMENT 'ç§ç®ç¼ç ', |
| | | `subject_name` varchar(128) DEFAULT NULL COMMENT 'ç§ç®åç§°', |
| | | `summary` varchar(500) DEFAULT NULL COMMENT 'æè¦', |
| | | `debit` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'åæ¹éé¢', |
| | | `credit` decimal(18,2) NOT NULL DEFAULT '0.00' COMMENT 'è´·æ¹éé¢', |
| | | `auxiliary_type` varchar(32) DEFAULT NULL COMMENT 'è¾
婿 ¸ç®ç±»å', |
| | | `auxiliary_id` varchar(64) DEFAULT NULL COMMENT 'è¾
婿 ¸ç®å¯¹è±¡ID', |
| | | `auxiliary_name` varchar(128) DEFAULT NULL COMMENT 'è¾
婿 ¸ç®å¯¹è±¡åç§°', |
| | | `create_user` varchar(64) DEFAULT NULL COMMENT 'å建人', |
| | | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | | `update_user` varchar(64) DEFAULT NULL COMMENT 'ä¿®æ¹äºº', |
| | | `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´', |
| | | `dept_id` bigint DEFAULT NULL COMMENT 'é¨é¨ID', |
| | | PRIMARY KEY (`id`), |
| | | KEY `idx_fin_voucher_entry_voucher` (`voucher_id`), |
| | | KEY `idx_fin_voucher_entry_subject` (`subject_code`), |
| | | KEY `idx_fin_voucher_entry_aux` (`auxiliary_type`, `auxiliary_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='åè¯åå½'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # è´¢å¡ç®¡ç模åå端èè°ææ¡£ï¼account 模åï¼ |
| | | |
| | | æ´æ°æ¶é´ï¼2026-05-12 |
| | | |
| | | ## 1. éç¨è¯´æ |
| | | |
| | | ### 1.1 ååºç»æ |
| | | æåååºï¼ |
| | | |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "æä½æå", |
| | | "data": {} |
| | | } |
| | | ``` |
| | | |
| | | ä¸å¡æ ¡éªå¤±è´¥ï¼ä¾å¦åè´·ä¸å¹³è¡¡ãå¿
填缺失ï¼ç±å
¨å±å¼å¸¸è¿åï¼ |
| | | |
| | | ```json |
| | | { |
| | | "code": 500, |
| | | "msg": "é误信æ¯", |
| | | "data": null |
| | | } |
| | | ``` |
| | | |
| | | ### 1.2 åé¡µç»æ |
| | | å页æ¥å£ç»ä¸ä½¿ç¨ MyBatis-Plus `Page`ï¼ |
| | | - 请æ±åæ°ï¼`current`ã`size` |
| | | - è¿åï¼`data.records`ã`data.total` |
| | | |
| | | --- |
| | | |
| | | ## 2. æ»è´¦ç§ç®ï¼å·²å¨åæ¥å£ä¸å¢å¼ºæ ¡éªï¼ |
| | | |
| | | æ¥å£ä¿æä¸åï¼ |
| | | - `GET /accountSubject/list` |
| | | - `POST /accountSubject/add` |
| | | - `PUT /accountSubject/edit` |
| | | - `DELETE /accountSubject/remove/{ids}` |
| | | - `POST /accountSubject/export` |
| | | |
| | | æ°å¢è§åï¼ |
| | | 1. `subjectCode`ã`subjectName`ã`subjectType` å¿
å¡«ã |
| | | 2. `subjectCode` å¯ä¸æ ¡éªã |
| | | 3. å é¤ååå¼ç¨æ ¡éªï¼è¥è¢«åè¯åå½(`fin_voucher_entry.subject_code`)å¼ç¨ï¼ç¦æ¢å é¤ã |
| | | |
| | | --- |
| | | |
| | | ## 3. åºå®èµäº§ |
| | | |
| | | Base URLï¼`/financial/fixedAsset` |
| | | |
| | | ### 3.1 å页æ¥è¯¢ |
| | | - `GET /page` |
| | | - Queryï¼`current,size,assetCode,assetName,category,status` |
| | | |
| | | ### 3.2 æ°å¢ |
| | | - `POST /add` |
| | | - Bodyï¼JSONï¼ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "assetCode": "GD20260512001", |
| | | "assetName": "åå
¬çµè", |
| | | "category": "electronic", |
| | | "specification": "ThinkPad X1", |
| | | "purchaseDate": "2026-05-01", |
| | | "originalValue": 8000.00, |
| | | "usefulLife": 5, |
| | | "residualRate": 5.00, |
| | | "location": "è´¢å¡é¨", |
| | | "department": "è´¢å¡é¨", |
| | | "keeper": "å¼ ä¸", |
| | | "status": "in_use", |
| | | "remark": "示ä¾" |
| | | } |
| | | ``` |
| | | |
| | | ### 3.3 ä¿®æ¹ |
| | | - `PUT /update` |
| | | - Bodyï¼åæ°å¢ï¼éå
å« `id` |
| | | |
| | | ### 3.4 å é¤ |
| | | - `DELETE /delete?ids=1&ids=2` |
| | | |
| | | ### 3.5 ææ§è®¡æï¼ææï¼ |
| | | - `POST /depreciate` |
| | | - Body å¯éï¼ |
| | | - å
¨é¨å¨ç¨èµäº§ï¼`{}` |
| | | - æå®èµäº§ï¼`{"ids":[1,2,3]}` |
| | | |
| | | æ ¸å¿å
¬å¼ï¼ |
| | | - `monthlyDepreciation = originalValue * (1 - residualRate/100) / (usefulLife*12)` |
| | | - `accumulatedDepreciation += monthlyDepreciation` |
| | | - `netValue = originalValue - accumulatedDepreciation` |
| | | |
| | | ç¶æå»ºè®®å¼ï¼ |
| | | - `in_use`ã`idle`ã`repair`ã`scrapped` |
| | | |
| | | --- |
| | | |
| | | ## 4. æ å½¢èµäº§ |
| | | |
| | | Base URLï¼`/financial/intangibleAsset` |
| | | |
| | | ### 4.1 å页æ¥è¯¢ |
| | | - `GET /page` |
| | | - Queryï¼`current,size,assetCode,assetName,category,status` |
| | | |
| | | ### 4.2 æ°å¢ |
| | | - `POST /add` |
| | | |
| | | ```json |
| | | { |
| | | "assetCode": "WX20260512001", |
| | | "assetName": "ERP软件许å¯", |
| | | "category": "software", |
| | | "certificateNo": "SW-001", |
| | | "acquisitionDate": "2026-05-01", |
| | | "originalValue": 50000.00, |
| | | "amortizationPeriod": 10, |
| | | "residualRate": 0.00, |
| | | "validityDate": "2036-05-01", |
| | | "status": "in_use", |
| | | "description": "示ä¾", |
| | | "remark": "" |
| | | } |
| | | ``` |
| | | |
| | | ### 4.3 ä¿®æ¹ |
| | | - `PUT /update` |
| | | - Bodyï¼åæ°å¢ï¼éå
å« `id` |
| | | |
| | | ### 4.4 å é¤ |
| | | - `DELETE /delete?ids=1&ids=2` |
| | | |
| | | ### 4.5 æé计æï¼ææï¼ |
| | | - `POST /amortize` |
| | | - Body å¯éï¼ |
| | | - å
¨é¨å¨ç¨èµäº§ï¼`{}` |
| | | - æå®èµäº§ï¼`{"ids":[1,2,3]}` |
| | | |
| | | æ ¸å¿å
¬å¼ï¼ |
| | | - `monthlyAmortization = originalValue * (1 - residualRate/100) / (amortizationPeriod*12)` |
| | | - `accumulatedAmortization += monthlyAmortization` |
| | | - `netValue = originalValue - accumulatedAmortization` |
| | | - å½ `netValue <= 0` æ¶ï¼`netValue=0` ä¸ `status=amortized` |
| | | |
| | | ç¶æå»ºè®®å¼ï¼ |
| | | - `in_use`ã`expired`ã`amortized` |
| | | |
| | | --- |
| | | |
| | | ## 5. åè¯ |
| | | |
| | | Base URLï¼`/financial/voucher` |
| | | |
| | | ### 5.1 å页æ¥è¯¢ |
| | | - `GET /page` |
| | | - Queryï¼`current,size,voucherNo,creator,status,startDate,endDate` |
| | | |
| | | ### 5.2 æ°å¢ |
| | | - `POST /add` |
| | | |
| | | ```json |
| | | { |
| | | "voucherNo": "è®°-0001", |
| | | "voucherDate": "2026-05-12", |
| | | "summary": "é宿¶å
¥", |
| | | "creator": "å¼ ä¸", |
| | | "attachmentCount": 0, |
| | | "remark": "", |
| | | "entries": [ |
| | | { |
| | | "subjectCode": "1002", |
| | | "subjectName": "é¶è¡å款", |
| | | "summary": "æ¶å°è´§æ¬¾", |
| | | "debit": 1000.00, |
| | | "credit": 0 |
| | | }, |
| | | { |
| | | "subjectCode": "6001", |
| | | "subjectName": "主è¥ä¸å¡æ¶å
¥", |
| | | "summary": "确认æ¶å
¥", |
| | | "debit": 0, |
| | | "credit": 1000.00 |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | ### 5.3 ä¿®æ¹ |
| | | - `PUT /update` |
| | | - Bodyï¼åæ°å¢ï¼éå
å« `id` |
| | | - ä»
`unposted` ç¶æå
è®¸ä¿®æ¹ |
| | | |
| | | ### 5.4 è¿è´¦ |
| | | - `POST /post` |
| | | |
| | | ```json |
| | | { |
| | | "id": 1 |
| | | } |
| | | ``` |
| | | |
| | | ### 5.5 ä½åº |
| | | - `POST /cancel` |
| | | |
| | | ```json |
| | | { |
| | | "id": 1 |
| | | } |
| | | ``` |
| | | |
| | | ### 5.6 详æ
|
| | | - `GET /detail/{id}` |
| | | |
| | | å
³é®æ ¡éªï¼ |
| | | 1. åå½è³å°ä¸æ¡ææè¡ï¼ç§ç®ä¸ç©ºï¼ä¸åæ¹æè´·æ¹ > 0ï¼ã |
| | | 2. æ¯æ¡ææåå½ä¸è½åè´·åæ¶å¤§äº 0ã |
| | | 3. å贷平衡ï¼`sum(debit) == sum(credit)` ä¸é½ > 0ã |
| | | 4. `subjectCode` å¿
é¡»åå¨äº `account_subject`ã |
| | | |
| | | ç¶ææµè½¬ï¼ |
| | | - `unposted -> posted` |
| | | - `unposted -> cancelled` |
| | | |
| | | --- |
| | | |
| | | ## 6. ç§ç®æ»è´¦ |
| | | |
| | | ### 6.1 æ¥è¯¢æ¥å£ |
| | | - `GET /financial/ledger/general` |
| | | |
| | | ### 6.2 Query åæ° |
| | | - `subjectCode`ï¼å¿
å¡«ï¼ |
| | | - `startMonth`ï¼YYYY-MMï¼ |
| | | - `endMonth`ï¼YYYY-MMï¼ |
| | | |
| | | ### 6.3 è¿ååæ®µ |
| | | - `rowType`ï¼`opening` / `entry` / `monthly_total` / `yearly_total` |
| | | - `date` |
| | | - `voucherNo` |
| | | - `summary` |
| | | - `debit` |
| | | - `credit` |
| | | - `direction`ï¼å/è´·ï¼ |
| | | - `balance`ï¼åæ£è´·è´ï¼ |
| | | |
| | | 说æï¼ |
| | | - ç§ç®æ¯æâæå®ç§ç®åå
¶ä¸çº§ï¼åç¼å¹é
ï¼âæ¥è¯¢ã |
| | | - èªå¨è¾åºâæåä½é¢ / æ¬æå计 / æ¬å¹´ç´¯è®¡âã |
| | | |
| | | --- |
| | | |
| | | ## 7. ç§ç®æç»è´¦ |
| | | |
| | | ### 7.1 æ¥è¯¢æ¥å£ |
| | | - `GET /financial/ledger/detail` |
| | | |
| | | ### 7.2 Query åæ° |
| | | - `subjectCode`ï¼å¿
å¡«ï¼ |
| | | - `auxiliaryType`ï¼å¯éï¼`customer/supplier/department/employee/project`ï¼ |
| | | - `auxiliaryId`ï¼å¯éï¼ |
| | | - `startMonth`ï¼YYYY-MMï¼ |
| | | - `endMonth`ï¼YYYY-MMï¼ |
| | | |
| | | ### 7.3 è¿ååæ®µ |
| | | åç§ç®æ»è´¦ï¼ |
| | | - `rowType,date,voucherNo,summary,debit,credit,direction,balance` |
| | | |
| | | --- |
| | | |
| | | ## 8. æ°æ®åºèæ¬ |
| | | |
| | | å·²æä¾èæ¬ï¼ |
| | | |
| | | - `doc/20260512_create_financial_management_tables.sql` |
| | | |
| | | å
å«ï¼ |
| | | - `fin_fixed_asset` |
| | | - `fin_intangible_asset` |
| | | - `fin_voucher` |
| | | - `fin_voucher_entry` |
| | | |
| | | æ»è´¦ç§ç®å¤ç¨ç°æ `account_subject`ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | ALTER TABLE `inspection_task` |
| | | ADD COLUMN `inspection_project` VARCHAR(100) NULL COMMENT 'å·¡æ£é¡¹ç®' AFTER `task_name`; |
| | | |
| | | ALTER TABLE `inspection_task` |
| | | ADD COLUMN `inspection_result` VARCHAR(1) NULL COMMENT 'å·¡æ£ç»æ 0å¼å¸¸ 1æ£å¸¸' AFTER `remarks`, |
| | | ADD COLUMN `abnormal_description` VARCHAR(500) NULL COMMENT 'å¼å¸¸æè¿°' AFTER `inspection_result`, |
| | | ADD COLUMN `device_repair_id` BIGINT NULL COMMENT 'å
³èç»´ä¿®åID' AFTER `abnormal_description`, |
| | | ADD COLUMN `acceptance_user_id` BIGINT NULL COMMENT 'éªæ¶äººID' AFTER `device_repair_id`, |
| | | ADD COLUMN `acceptance_name` VARCHAR(100) NULL COMMENT 'éªæ¶äºº' AFTER `acceptance_user_id`; |
| | | |
| | | ALTER TABLE `timing_task` |
| | | ADD COLUMN `inspection_project` VARCHAR(100) NULL COMMENT 'å·¡æ£é¡¹ç®' AFTER `task_name`, |
| | | ADD COLUMN `is_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'æ¯å¦å¯ç¨ 0å¦ 1æ¯' AFTER `is_active`; |
| | | |
| | | CREATE INDEX `idx_inspection_task_device_repair_id` |
| | | ON `inspection_task` (`device_repair_id`); |
| | | |
| | | CREATE INDEX `idx_inspection_task_inspection_result` |
| | | ON `inspection_task` (`inspection_result`); |
| | | |
| | | CREATE INDEX `idx_timing_task_is_enabled` |
| | | ON `timing_task` (`is_enabled`); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 设å¤å·¡æ£ä¸å®æ¶å·¡æ£å端èè°ææ¡£ï¼inspectiontaskï¼ |
| | | |
| | | > æ´æ°æ¥æï¼2026-05-15 |
| | | > éç¨æ¨¡åï¼è®¾å¤å·¡æ£ä»»å¡ `inspectiontask`ï¼`/inspectionTask`ï¼ä¸å®æ¶å·¡æ£ä»»å¡ï¼`/timingTask`ï¼ |
| | | |
| | | ## 1. æ¬æ¬¡æ¹å¨ |
| | | |
| | | 1. å·¡æ£ä»»å¡æ°å¢åæ®µï¼ |
| | | - `inspectionProject`ï¼å·¡æ£é¡¹ç®ï¼ |
| | | - `inspectionResult`ï¼å·¡æ£ç»æï¼`0`å¼å¸¸ / `1`æ£å¸¸ï¼å¿
å¡«ï¼ |
| | | - `abnormalDescription`ï¼å¼å¸¸æè¿°ï¼ |
| | | - `deviceRepairId`ï¼å
³èç»´ä¿®åIDï¼å¼å¸¸æ¶å端èªå¨åå¡«ï¼ |
| | | - `acceptanceUserId`ï¼éªæ¶äººIDï¼ |
| | | - `acceptanceName`ï¼éªæ¶äººï¼ |
| | | 2. å¼å¸¸æ ¡éªè§åï¼ |
| | | - `inspectionResult=1`ï¼æ£å¸¸ï¼ï¼ç
§çéå¿
å¡«ã |
| | | - `inspectionResult=0`ï¼å¼å¸¸ï¼ï¼å¿
é¡»æç
§çï¼ä¸å¿
须填å `abnormalDescription`ã |
| | | 3. å¼å¸¸èå¨è§åï¼ |
| | | - å¼å¸¸ä¿ååèªå¨çæ `device_repair` å¹¶åå¡« `deviceRepairId`ã |
| | | 4. 宿¶ä»»å¡æ°å¢åæ®µï¼ |
| | | - `inspectionProject`ï¼å·¡æ£é¡¹ç®ï¼ |
| | | - `isEnabled`ï¼æ¯å¦å¯ç¨ï¼`0`å¦ / `1`æ¯ï¼ |
| | | 5. 夿³¨å¸¦å
¥è§åï¼ |
| | | - 宿¶ä»»å¡èªå¨çæå·¡æ£è®°å½æ¶ï¼è¥å®æ¶ä»»å¡ `remarks` æå¼ï¼ä¼æ¼æ¥å°å·¡æ£è®°å½å¤æ³¨ä¸ã |
| | | |
| | | ## 2. æ°æ®åºåæ´ |
| | | |
| | | èè°åæ§è¡ SQLï¼ |
| | | |
| | | - [doc/20260515_device_maintenance_inspection_abnormal_acceptance.sql](/D:/ç马/åé/å端/product-inventory-management-after-jdk25/doc/20260515_device_maintenance_inspection_abnormal_acceptance.sql) |
| | | |
| | | > 说æï¼è¯¥èæ¬å½åä½ç¨äº `inspection_task` ä¸ `timing_task` ä¸¤å¼ è¡¨ï¼æä»¶ååå²ä¿çæªæ¹ã |
| | | |
| | | ## 3. å·¡æ£ä»»å¡æ¥å£ |
| | | |
| | | ### 3.1 ä¿åæ¥å£ |
| | | |
| | | `POST /inspectionTask/addOrEditInspectionTask` |
| | | |
| | | | åæ®µ | ç±»å | å¿
å¡« | 说æ | |
| | | |---|---|---|---| |
| | | | id | long | å¦ | æå¼=ä¿®æ¹ï¼æ å¼=æ°å¢ | |
| | | | taskId | int | 建议å¿
å¡« | 设å¤IDï¼ç¨äºå¼å¸¸èªå¨å»ºç»´ä¿®åï¼ | |
| | | | taskName | string | 建议å¿
å¡« | 设å¤åç§° | |
| | | | inspectionProject | string | å¦ | å·¡æ£é¡¹ç® | |
| | | | inspectorId | string | å¦ | å·¡æ£äººIDï¼æ¯æéå·åé | |
| | | | inspectionResult | string | æ¯ | `0`=å¼å¸¸ï¼`1`=æ£å¸¸ | |
| | | | abnormalDescription | string | æ¡ä»¶å¿
å¡« | å¼å¸¸æ¶å¿
å¡« | |
| | | | acceptanceUserId | long | å¦ | éªæ¶äººID | |
| | | | acceptanceName | string | å¦ | éªæ¶äººå§å | |
| | | | commonFileListDTO | array | æ¡ä»¶å¿
å¡« | éä»¶ç»1ï¼å¼å¸¸æ¶ä¸ç»è³å°ä¸ç»æå¾ï¼ | |
| | | | commonFileListAfterDTO | array | æ¡ä»¶å¿
å¡« | éä»¶ç»2ï¼å¼å¸¸æ¶ä¸ç»è³å°ä¸ç»æå¾ï¼ | |
| | | | commonFileListBeforeDTO | array | æ¡ä»¶å¿
å¡« | éä»¶ç»3ï¼å¼å¸¸æ¶ä¸ç»è³å°ä¸ç»æå¾ï¼ | |
| | | |
| | | å¼å¸¸ç¤ºä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "taskId": 1001, |
| | | "taskName": "ç©ºåæºA-01", |
| | | "inspectionProject": "润æ»ç³»ç»", |
| | | "inspectorId": "12", |
| | | "inspectionResult": "0", |
| | | "abnormalDescription": "çµæºå¼åï¼æ¸©ååé«", |
| | | "acceptanceUserId": 20, |
| | | "commonFileListDTO": [ |
| | | { |
| | | "id": 90001, |
| | | "application": "file" |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | æ£å¸¸ç¤ºä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "taskId": 1001, |
| | | "taskName": "ç©ºåæºA-01", |
| | | "inspectionProject": "ç¹æ£", |
| | | "inspectorId": "12", |
| | | "inspectionResult": "1", |
| | | "acceptanceUserId": 20 |
| | | } |
| | | ``` |
| | | |
| | | ### 3.2 å表æ¥å£ |
| | | |
| | | `GET /inspectionTask/list` |
| | | |
| | | è¿åå
嫿°å¢åæ®µï¼ |
| | | |
| | | - `inspectionProject` |
| | | - `inspectionResult` |
| | | - `abnormalDescription` |
| | | - `deviceRepairId` |
| | | - `acceptanceUserId` |
| | | - `acceptanceName` |
| | | |
| | | ## 4. 宿¶ä»»å¡æ¥å£ |
| | | |
| | | ### 4.1 ä¿åæ¥å£ |
| | | |
| | | `POST /timingTask/addOrEditTimingTask` |
| | | |
| | | æ°å¢/æ´æ°åæ®µï¼ |
| | | |
| | | | åæ®µ | ç±»å | å¿
å¡« | 说æ | |
| | | |---|---|---|---| |
| | | | inspectionProject | string | å¦ | å·¡æ£é¡¹ç® | |
| | | | remarks | string | å¦ | 夿³¨ | |
| | | | isEnabled | int | å¦ | `0`=ç¦ç¨ï¼`1`=å¯ç¨ï¼ä¸ä¼ é»è®¤å¯ç¨ | |
| | | |
| | | 示ä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "taskName": "ç©ºåæºA-01宿¶å·¡æ£", |
| | | "inspectionProject": "æåº¦å·¡æ£", |
| | | "taskId": 1001, |
| | | "inspectorIds": "12,13", |
| | | "frequencyType": "DAILY", |
| | | "frequencyDetail": "09:00", |
| | | "remarks": "éç¹æ£æ¥è½´æ¿æ¸©åº¦", |
| | | "isEnabled": 1 |
| | | } |
| | | ``` |
| | | |
| | | ### 4.2 å¯ç¨ç¶æè¡ä¸º |
| | | |
| | | 1. `isEnabled=1`ï¼ä»»å¡è¿å
¥è°åº¦ï¼æé¢æ¬¡èªå¨çæå·¡æ£è®°å½ã |
| | | 2. `isEnabled=0`ï¼ä»»å¡ä¸è°åº¦ï¼å·²åå¨è°åº¦ä¼è¢«ç§»é¤ã |
| | | |
| | | ### 4.3 夿³¨å¸¦å
¥è§å |
| | | |
| | | 宿¶ä»»å¡èªå¨çæå·¡æ£è®°å½æ¶ï¼ |
| | | |
| | | 1. å·¡æ£è®°å½å¤æ³¨åºå®åç¼ï¼`èªå¨çæèªå®æ¶ä»»å¡ID: {id}` |
| | | 2. å½å®æ¶ä»»å¡ `remarks` é空æ¶ï¼æ¼æ¥ä¸ºï¼ |
| | | `èªå¨çæèªå®æ¶ä»»å¡ID: {id}ï¼{remarks}` |
| | | |
| | | ## 5. å¼å¸¸èªå¨å»ºç»´ä¿®åè§å |
| | | |
| | | å½å·¡æ£è®°å½ `inspectionResult=0` æ¶ï¼ |
| | | |
| | | 1. è¥ `deviceRepairId` 为空ï¼å端èªå¨å建 `device_repair`ï¼ |
| | | - `deviceLedgerId`ï¼æ¥èª `taskId` |
| | | - `deviceName`ï¼ä¼å
`taskName`ï¼å¦åå设å¤å°è´¦åç§° |
| | | - `remark`ï¼å¼å¸¸æè¿° |
| | | - `status`ï¼`0`ï¼å¾
ç»´ä¿®ï¼ |
| | | 2. è¥å·²æå
³èç»´ä¿®åï¼ä»
åæ¥æ´æ°ç»´ä¿®å `remark`ã |
| | | |
| | | ## 6. å端æ¹é 建议 |
| | | |
| | | 1. å·¡æ£è¡¨åæ°å¢ `inspectionProject` è¾å
¥æ¡ã |
| | | 2. å·¡æ£è¡¨åä¿çâæ£å¸¸/å¼å¸¸âè卿 ¡éªï¼ |
| | | - å¼å¸¸æ¶å¼ºå¶å¼å¸¸æè¿° + è³å°ä¸ç»å¾çã |
| | | 3. 宿¶ä»»å¡è¡¨åæ°å¢âæ¯å¦å¯ç¨âå¼å
³å¹¶æ å° `isEnabled`ã |
| | | 4. 宿¶ä»»å¡è¡¨åæ°å¢ `inspectionProject` ä¸ `remarks` è¾å
¥é¡¹ã |
| | | 5. å·¡æ£å表å±ç¤º `inspectionProject` å `deviceRepairId`ï¼æ¯æè·³è½¬ç»´ä¿®å详æ
ï¼ã |
| | | |
| | | ## 7. èè°éªæ¶æ¸
å |
| | | |
| | | 1. å·¡æ£æ°å¢/ä¿®æ¹å¯æ£ç¡®æäº¤ `inspectionProject` å¹¶å¨åè¡¨åæ¾ã |
| | | 2. å¼å¸¸å·¡æ£ï¼ææè¿°+æå¾ï¼ä¿åæåå¹¶åå¡« `deviceRepairId`ã |
| | | 3. å¼å¸¸å·¡æ£ç¼ºæè¿°æç¼ºå¾çæ¶è¢«æ¦æªã |
| | | 4. 宿¶ä»»å¡ `isEnabled=0` æ¶ä¸å触åèªå¨å·¡æ£è®°å½ã |
| | | 5. 宿¶ä»»å¡ `isEnabled=1` æ¶æé¢æ¬¡çæå·¡æ£è®°å½ã |
| | | 6. 宿¶ä»»å¡æ `remarks` æ¶ï¼èªå¨å·¡æ£è®°å½å¤æ³¨å¸¦ä¸è¯¥å
容ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å¶é æºè½å©æå端èè°ææ¡£ï¼`manufacturing-ai`ï¼ |
| | | |
| | | > æ´æ°æ¥æï¼2026-05-16 |
| | | > éç¨æ¨¡åï¼ç产ç°åºã计åãå·¥åã设å¤ãè´¨éãç©æãå¼å¸¸å¤ç |
| | | > è½åèå´ï¼æ¥ãé®ãåãé¢è¦ãåæ |
| | | |
| | | ## 1. æ¥å£æ»è§ |
| | | |
| | | 1. æµå¼å¯¹è¯ï¼`POST /manufacturing-ai/chat` |
| | | 2. ä¼è¯å表ï¼`GET /manufacturing-ai/history/sessions` |
| | | 3. ä¼è¯æ¶æ¯ï¼`GET /manufacturing-ai/history/messages/{memoryId}` |
| | | 4. å é¤ä¼è¯ï¼`DELETE /manufacturing-ai/history/{memoryId}` |
| | | |
| | | 说æï¼ |
| | | - `/chat` 为 **SSE/æµå¼ææ¬** è¿åï¼`text/stream;charset=utf-8`ï¼ã |
| | | - å½ä¸âæ¥/é¢è¦/åæ/åâå·¥å
·æ¶ï¼æµå¼æç»å
å®¹æ¯ **JSON å符串**ï¼ä¸æ¯ `AjaxResult`ï¼ã |
| | | - æªå½ä¸å·¥å
·æ¶ï¼è¿åæ®éèªç¶è¯è¨ææ¬ã |
| | | |
| | | ## 2. é´æä¸è¯·æ±å¤´ |
| | | |
| | | - ç»ä¸ä½¿ç¨ç³»ç»ç»å½æï¼`Authorization` ä¸ç°ææ¥å£ä¸è´ï¼ã |
| | | - `POST /manufacturing-ai/chat` 请æ±å¤´ï¼`Content-Type: application/json`ã |
| | | |
| | | ## 3. å¯¹è¯æ¥å£ |
| | | |
| | | ### 3.1 è¯·æ± |
| | | |
| | | ```http |
| | | POST /manufacturing-ai/chat |
| | | Content-Type: application/json |
| | | ``` |
| | | |
| | | ```json |
| | | { |
| | | "memoryId": "mfg-ai-001", |
| | | "message": "æ¥è®¾å¤è¥¿é¨ååé¢å¨çç»´ä¿®æ
åµ" |
| | | } |
| | | ``` |
| | | |
| | | åæ®µè¯´æï¼ |
| | | |
| | | | åæ®µ | ç±»å | å¿
å¡« | 说æ | |
| | | | --- | --- | --- | --- | |
| | | | memoryId | string | æ¯ | ä¼è¯ IDï¼å端çæå¹¶å¤ç¨ | |
| | | | message | string | æ¯ | ç¨æ·è¾å
¥ | |
| | | |
| | | ### 3.2 è¿åï¼æµå¼ï¼ |
| | | |
| | | ```http |
| | | Content-Type: text/stream;charset=utf-8 |
| | | ``` |
| | | |
| | | å端å¤çå»ºè®®ï¼ |
| | | 1. ææµæ¼æ¥å®æ´ææ¬ã |
| | | 2. å°è¯ `JSON.parse(fullText)`ï¼ |
| | | - æåï¼æç»æåç»ææ¸²æã |
| | | - å¤±è´¥ï¼ææ®éèå¤©ææ¬æ¸²æã |
| | | |
| | | ## 4. ç»æåååºåè®® |
| | | |
| | | ### 4.1 éç¨ç»æ |
| | | |
| | | ```json |
| | | { |
| | | "success": true, |
| | | "type": "manufacturing_device_repair_list", |
| | | "description": "å·²è¿å设å¤ç»´ä¿®è®°å½ã", |
| | | "summary": {}, |
| | | "data": {}, |
| | | "charts": {} |
| | | } |
| | | ``` |
| | | |
| | | ### 4.2 `type` æä¸¾ |
| | | |
| | | | type | åºæ¯ | |
| | | | --- | --- | |
| | | | manufacturing_site_snapshot | ç产ç°åºæ¦è§ | |
| | | | manufacturing_plan_list | çäº§è®¡åæ¥è¯¢ | |
| | | | manufacturing_workorder_list | å·¥åæ¥è¯¢ | |
| | | | manufacturing_device_list | 设å¤å°è´¦æ¥è¯¢ | |
| | | | manufacturing_device_repair_list | 设å¤ç»´ä¿®è®°å½æ¥è¯¢ | |
| | | | manufacturing_quality_list | è´¨éæ¥è¯¢ | |
| | | | manufacturing_material_list | ç©æåºåæ¥è¯¢ | |
| | | | manufacturing_exception_list | å¼å¸¸å¤çæ¥è¯¢ | |
| | | | manufacturing_warning | é¢è¦çæ¿ | |
| | | | manufacturing_analysis | ç»è¥åæ | |
| | | | manufacturing_action_plan | åç建议ï¼å¨ä½å¡ï¼ | |
| | | |
| | | ## 5. âæ¥âè½åèè°è¦ç¹ |
| | | |
| | | ### 5.1 设å¤ç¸å
³è·¯ç±è§åï¼å
³é®ï¼ |
| | | |
| | | - å½ç¨æ·è¾å
¥å
å« `ç»´ä¿®/æ¥ä¿®/æ£ä¿®/ç»´æ¤`ï¼è®¾å¤åä¼è¿å `manufacturing_device_repair_list`ï¼æ¥ `device_repair`ï¼ã |
| | | - æªå
å«ä»¥ä¸è¯æ¶ï¼è¿å `manufacturing_device_list`ï¼æ¥è®¾å¤å°è´¦ï¼ã |
| | | |
| | | 示ä¾ï¼ |
| | | - `æ¥è®¾å¤A-01` -> `manufacturing_device_list` |
| | | - `æ¥è®¾å¤A-01ç»´ä¿®æ
åµ` -> `manufacturing_device_repair_list` |
| | | |
| | | ### 5.2 ç»´ä¿®è®°å½æ¶é´è¿æ»¤è§åï¼å
³é®ï¼ |
| | | |
| | | - ç¨æ·æç¡®å¸¦æ¶é´æ¡ä»¶ï¼å¦âæ¬æ/ä¸å¨/è¿7天/2026-05-01 å° 2026-05-16âï¼æææ¶é´è¿æ»¤ç»´ä¿®è®°å½ã |
| | | - æªå¸¦æ¶é´æ¡ä»¶æ¶ï¼ä¸é»è®¤æè¿ 30 å¤©æªæï¼é¿å
åå²ç»´ä¿®è®°å½è¢«è¯¯è¿æ»¤ã |
| | | |
| | | ### 5.3 å
³é®è¯å¤çè§åï¼è®¾å¤/ç»´ä¿®ï¼ |
| | | |
| | | - ç³»ç»ä¼æ¸
æ´åªé³è¯ï¼`æ¥è¯¢/æ¥ç/请/设å¤/ç»´ä¿®æ
åµ/è®°å½/ä¿¡æ¯` çã |
| | | - åæ¶ä¼éè¿è®¾å¤å°è´¦å¹é
`deviceLedgerId` å
åºï¼ååæ¥ç»´ä¿®è®°å½ï¼éä½âææ°æ®ä½æ¥ä¸å°âçæ¦çã |
| | | |
| | | ### 5.4 åè¡¨ç»æçº¦å® |
| | | |
| | | - åè¡¨æ°æ®ç»ä¸å¨ `data.items` |
| | | - ç»è®¡æè¦å¨ `summary` |
| | | |
| | | 常ç¨åæ®µï¼ |
| | | |
| | | | type | 常ç¨å段 | |
| | | | --- | --- | |
| | | | manufacturing_plan_list | `mpsNo`, `requiredDate`, `status` | |
| | | | manufacturing_workorder_list | `workOrderNo`, `planStartTime`, `planEndTime`, `status` | |
| | | | manufacturing_device_list | `deviceName`, `deviceModel`, `pendingRepairCount` | |
| | | | manufacturing_device_repair_list | `deviceName`, `deviceModel`, `repairTime`, `repairName`, `maintenanceName`, `status`, `createTime` | |
| | | |
| | | ## 6. âé¢è¦âèè°è¦ç¹ |
| | | |
| | | - `type = manufacturing_warning` |
| | | - é¢è¦æç»å¨ `data.items`ï¼æ¯é¡¹å
å«ï¼ |
| | | - `level`ï¼`high` / `medium` |
| | | - `title` |
| | | - `count` |
| | | - `detail` |
| | | |
| | | ç¶æå£å¾ï¼ |
| | | - 设å¤âå¾
ç»´ä¿®âç»è®¡æ `status = 0` 计ç®ï¼ä¸åæå
¶ä»ç¶æè®¡å
¥å¾
ç»´ä¿®ï¼ã |
| | | |
| | | ## 7. âåæâèè°è¦ç¹ |
| | | |
| | | - `type = manufacturing_analysis` |
| | | - å
³é®ææ å¨ `summary` |
| | | - ææ å¡å¨ `data.coreMetrics` |
| | | - å¾è¡¨é
ç½®å¨ `charts`ï¼ |
| | | - `charts.domainBarOption` |
| | | - `charts.qualityPieOption` |
| | | |
| | | å¾è¡¨é
ç½®å¯ç´æ¥ç» ECharts 使ç¨ã |
| | | |
| | | ## 8. âåâè½åèè°è¦ç¹ |
| | | |
| | | å½åâåâ为 **åç建议模å¼**ï¼AI è¾åºå¨ä½å¡ï¼å端确认åè°ç¨ç®æ ä¸å¡æ¥å£ï¼ã |
| | | |
| | | - `type = manufacturing_action_plan` |
| | | - å¨ä½å¡æ°ç»ï¼`data.actionCards` |
| | | |
| | | å¨ä½å¡åæ®µï¼ |
| | | |
| | | | åæ®µ | 说æ | |
| | | | --- | --- | |
| | | | code | å¨ä½ç¼ç | |
| | | | name | å¨ä½åç§° | |
| | | | method | è¯·æ±æ¹æ³ | |
| | | | targetApi | ç®æ ä¸å¡æ¥å£ | |
| | | | requiredFields | å¿
å¡«åæ®µ | |
| | | | examplePayload | 示ä¾åæ° | |
| | | | description | 说æ | |
| | | |
| | | å
ç½®å¨ä½ç¤ºä¾ï¼ |
| | | 1. `POST /productionOperationTask/assign` |
| | | 2. `POST /device/repair` |
| | | 3. `POST /quality/qualityUnqualified/deal` |
| | | 4. `POST /stockInventory/addstockInventory` |
| | | 5. `POST /procurementExceptionRecord/add` |
| | | |
| | | ## 9. ä¼è¯ç®¡çæ¥å£ |
| | | |
| | | ### 9.1 ä¼è¯å表 |
| | | |
| | | ```http |
| | | GET /manufacturing-ai/history/sessions |
| | | ``` |
| | | |
| | | `AjaxResult.data` åæ®µï¼ |
| | | - `memoryId` |
| | | - `title` |
| | | - `lastMessage` |
| | | - `messageCount` |
| | | - `lastChatTime` |
| | | |
| | | ### 9.2 ä¼è¯æ¶æ¯ |
| | | |
| | | ```http |
| | | GET /manufacturing-ai/history/messages/{memoryId} |
| | | ``` |
| | | |
| | | `AjaxResult.data` åæ®µï¼ |
| | | - `role`ï¼`user` / `assistant` / `system` / `tool` |
| | | - `content` |
| | | - `filePaths` |
| | | |
| | | ### 9.3 å é¤ä¼è¯ |
| | | |
| | | ```http |
| | | DELETE /manufacturing-ai/history/{memoryId} |
| | | ``` |
| | | |
| | | è¿åæ å `AjaxResult`ã |
| | | |
| | | ## 10. é误ä¸è¾¹ç |
| | | |
| | | `/chat` 常è§è¿åææ¬ï¼ |
| | | - `memoryIdä¸è½ä¸ºç©º` |
| | | - `messageä¸è½ä¸ºç©º` |
| | | |
| | | 建议å端åéåå
åå¿
å¡«æ ¡éªã |
| | | |
| | | ## 11. å端èè°æµç¨å»ºè®® |
| | | |
| | | 1. ç»å½åå建并å¤ç¨ `memoryId`ã |
| | | 2. è°ç¨ `/manufacturing-ai/chat`ï¼æ SSE æ¼æ¥å®æ´ææ¬ã |
| | | 3. å
å°è¯ JSON è§£æï¼ |
| | | - æåï¼æ `type` è·¯ç±å°å¯¹åº UIï¼å表/é¢è¦/åæ/å¨ä½å¡ï¼ã |
| | | - å¤±è´¥ï¼ææ®éèå¤©æ¶æ¯å±ç¤ºã |
| | | 4. âåâåºæ¯ç±ç¨æ·ç¡®è®¤å¨ä½å¡åï¼å端è°ç¨ `targetApi` 宿ä¸å¡æäº¤ã |
| | | 5. éè¿å岿¥å£åä¼è¯åæ¾ä¸å é¤ã |
| | | |
| | | ## 12. å端éæçº¦æï¼æ¬æ¬¡è¡¥å
ï¼ |
| | | |
| | | ### 12.1 æºè½ä½æ°å¢ä¸å¼¹çªåæ¥è§åï¼å¼ºå¶ï¼ |
| | | |
| | | 1. å½ `src/views/aiIndustrialBrain/index.vue` æ°å¢æºè½ä½ï¼`agents`ï¼é»è¾æ¶ï¼å¿
é¡»åæ¥ç¡®è®¤å¼¹çªå©æå¯ç¨æ§ã |
| | | 2. å¼¹çªå©æç»ä¸ç± `src/components/AIChatSidebar/assistants/index.js` ç `assistantRegistry` 注åã |
| | | 3. æ°å¢æºè½ä½ç `key` è¥è¦å¨å¼¹çªä¸å¯ç¨ï¼å¿
é¡»å¨ `assistantRegistry` 䏿ä¾ååé
ç½®ã |
| | | 4. æªå¨ `assistantRegistry` 注åçæºè½ä½ï¼å¼¹çªæ¾ç¤ºä¸º `pending`ï¼å¼åä¸ï¼æã |
| | | |
| | | ### 12.2 çäº§å©ææ¥å
¥çº¦å® |
| | | |
| | | 1. çäº§å©æé
ç½®ä½äº `src/components/AIChatSidebar/assistants/productionAssistant.js`ï¼`apiBase = /manufacturing-ai`ã |
| | | 2. AI å·¥ä¸å¤§èä¸ç产æºè½ä½è¿å
¥å¼¹çªåï¼é»è®¤ä½¿ç¨ `production` 婿ã |
| | | 3. å
¨å±å³ä¾§å¯¹è¯æ¡å©æåæ¢å表已å
å«ï¼ |
| | | - `general`ï¼å¾
åå©çï¼ |
| | | - `purchase`ï¼éè´å©çï¼ |
| | | - `production`ï¼ç产å©çï¼ |
| | | |
| | | ### 12.3 åæ®µä¸æåå±ç¤ºè§å |
| | | |
| | | 1. é¢åä¸å¡ç¨æ·çåæ®µåãæ ç¾ãå¿
å¡«æç¤ºä¸ç´æ¥å±ç¤ºè±æ keyã |
| | | 2. `requiredFields`ã`missingFields` æç¤ºé转æ¢ä¸ºä¸æè·¯å¾æ ç¾ï¼ç¤ºä¾ï¼`缺å°å¿
å¡«åæ®µï¼å·¥åå·ã计åç»ææ¶é´`ï¼ã |
| | | 3. ç»æåå表ååãæè¦ææ ãå¨ä½å¡å段ä¼å
æ¾ç¤ºä¸æï¼è±æ key ä»
ç¨äºæ¥å£éä¿¡ä¸è°è¯ã |
| | | |
| | | ## 13. æ¬æ¬¡æ´æ°è®°å½ï¼2026-05-16ï¼ |
| | | |
| | | 1. æ°å¢è®¾å¤ç»´ä¿®è®°å½è¿åç±»åï¼`manufacturing_device_repair_list`ã |
| | | 2. ä¿®æ£è®¾å¤åæå¾åæµï¼`ç»´ä¿®/æ¥ä¿®/æ£ä¿®/ç»´æ¤` 走维修记å½ï¼ä¸å误走设å¤å表ã |
| | | 3. ä¿®æ£ç»´ä¿®è®°å½æ¶é´è¿æ»¤ï¼ä»
å¨ç¨æ·æç¡®æ¶é´æ¡ä»¶æ¶çæã |
| | | 4. ä¿®æ£å¾
ç»´ä¿®ç»è®¡å£å¾ï¼æ `status = 0` ç»è®¡ã |
| | | 5. æ°å¢ AI å·¥ä¸å¤§èæºè½ä½ä¸å¼¹çªåæ¥ç»´æ¤è§åï¼æ°å¢æºè½ä½å¿
é¡»åæ¥æ³¨åå¼¹çªå©æã |
| | | 6. çäº§å©æå·²æ¥å
¥å·¥ä¸å¤§èå¼¹çªä¸å
¨å±å³ä¾§å¯¹è¯æ¡å©æåæ¢ã |
| | | 7. å¢å åæ®µä¸æåå±ç¤ºçº¦æï¼é¿å
è±æåæ®µå¯¹ä¸å¡ç¨æ·ç´åºã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å端èè°ææ¡£ï¼è®¾å¤æ¥ä¿® / 设å¤ä¿å
»å®æ¶ä»»å¡ / è´¢å¡ç§ç®æ»è´¦ï¼ |
| | | |
| | | ## 1. åæ´èå´ |
| | | |
| | | æ¬æ¬¡èè°æ¶å 3 个模åï¼ |
| | | |
| | | 1. è´¢å¡æ¨¡åï¼ç§ç®æ»è´¦å»æåè¯åå·ãæè¦ï¼åªè¿å 1 æ¡åè®¡æ°æ®ã |
| | | 2. 设å¤ä¿å
»å®æ¶ä»»å¡ï¼æ°å¢ `ä¿å
»äºº` åæ®µï¼å®æ¶ä»»å¡çæä¿å
»è®°å½æ¶å¸¦å
¥ã |
| | | 3. è®¾å¤æ¥ä¿®ï¼ç¡®è®¤æ¥ä¿®åæ°å¢éªæ¶å®¡æ¹ï¼éªæ¶éè¿åæç®å®ç»ã |
| | | |
| | | --- |
| | | |
| | | ## 2. æ¥å£æ¸
å |
| | | |
| | | ### 2.1 è´¢å¡-ç§ç®æ»è´¦ |
| | | |
| | | - **GET** `/financial/ledger/general` |
| | | - 说æï¼è¿åç§ç®æ»è´¦å计ï¼ä»
1 æ¡è®°å½ã |
| | | |
| | | #### 请æ±åæ°ï¼Queryï¼ |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |---|---|---|---| |
| | | | `subjectCode` | string | æ¯ | ç§ç®ç¼ç | |
| | | | `startMonth` | string | æ¯ | å¼å§æä»½ï¼æ ¼å¼ `YYYY-MM` | |
| | | | `endMonth` | string | æ¯ | ç»ææä»½ï¼æ ¼å¼ `YYYY-MM` | |
| | | |
| | | #### è¿åç»æ |
| | | |
| | | `R<List<FinLedgerRowVo>>` |
| | | |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "æä½æå", |
| | | "data": [ |
| | | { |
| | | "rowType": "yearly_total", |
| | | "date": "2026-05-31", |
| | | "debit": 12000.00, |
| | | "credit": 8000.00, |
| | | "direction": "å", |
| | | "balance": 4000.00 |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | #### èè°æ³¨æ |
| | | |
| | | 1. `data` åºå®åªæ 1 æ¡ï¼å计ï¼ã |
| | | 2. `voucherNo`ã`summary` ä¸è¿åï¼ä¸åå±ç¤ºåè¯åå·ãæè¦ï¼ã |
| | | |
| | | --- |
| | | |
| | | ### 2.2 设å¤ä¿å
»å®æ¶ä»»å¡ï¼æ°å¢ä¿å
»äººï¼ |
| | | |
| | | - åºç¡è·¯å¾ï¼`/deviceMaintenanceTask` |
| | | - ç¸å
³æ¥å£ï¼ |
| | | - **POST** `/add` |
| | | - **POST** `/update` |
| | | - **GET** `/listPage` |
| | | |
| | | #### æ°å¢å段 |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |---|---|---| |
| | | | `maintenancePerson` | string | ä¿å
»äºº | |
| | | |
| | | #### æ°å¢/æ´æ°è¯·æ±ç¤ºä¾ |
| | | |
| | | ```json |
| | | { |
| | | "id": 1, |
| | | "taskName": "ç©ºåæºä¿å
»ä»»å¡", |
| | | "taskId": 1001, |
| | | "maintenancePerson": "å¼ ä¸", |
| | | "frequencyType": "MONTHLY", |
| | | "frequencyDetail": "10,09:00", |
| | | "remarks": "æ¯æä¾è¡ä¿å
»" |
| | | } |
| | | ``` |
| | | |
| | | #### 宿¶ä»»å¡ä¸åè¡ä¸º |
| | | |
| | | 宿¶ä»»å¡æ§è¡åï¼ç³»ç»èªå¨å建ä¿å
»è®°å½ï¼`device_maintenance`ï¼æ¶ä¼åå
¥ï¼ |
| | | |
| | | - `maintenanceActuallyName = maintenancePerson` |
| | | |
| | | å³å端å¨å®æ¶ä»»å¡éç»´æ¤çä¿å
»äººï¼ä¼èªå¨å¸¦å
¥å°ä¿å
»è®°å½ã |
| | | |
| | | --- |
| | | |
| | | ### 2.3 è®¾å¤æ¥ä¿®ï¼ç¡®è®¤åéªæ¶å®¡æ¹ï¼ |
| | | |
| | | - åºç¡è·¯å¾ï¼`/device/repair` |
| | | |
| | | #### ç¶æå®ä¹ |
| | | |
| | | | ç¶æå¼ | å«ä¹ | |
| | | |---|---| |
| | | | `0` | å¾
ç»´ä¿® | |
| | | | `3` | å¾
éªæ¶ | |
| | | | `1` | å®ç» | |
| | | | `2` | 失败 | |
| | | |
| | | #### 2.3.1 维修确认ï¼å确认æ¥ä¿®ï¼ |
| | | |
| | | - **POST** `/device/repair/repair` |
| | | - 说æï¼æäº¤åç¶æä» `å¾
ç»´ä¿®(0)` è¿å
¥ `å¾
éªæ¶(3)`ï¼ä¸åç´æ¥å®ç»ã |
| | | |
| | | 请æ±ç¤ºä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "id": 10001, |
| | | "maintenanceName": "æå", |
| | | "maintenanceTime": "2026-05-14 10:30:00", |
| | | "maintenanceResult": "æ´æ¢è½´æ¿å¹¶è¯è¿è¡æ£å¸¸", |
| | | "sparePartsUseList": [ |
| | | { |
| | | "id": 501, |
| | | "quantity": 2 |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | 常è§å¤±è´¥æç¤ºï¼ç¨äºå端弹çªï¼ï¼ |
| | | |
| | | - `æ¥ä¿®è®°å½ä¸åå¨` |
| | | - `该æ¥ä¿®å·²å®ç»ï¼ä¸è½éå¤ç¡®è®¤ç»´ä¿®` |
| | | - `该æ¥ä¿®å·²æäº¤éªæ¶å®¡æ¹` |
| | | - `å¤ä»¶ xxx æ°éä¸è¶³` |
| | | |
| | | #### 2.3.2 éªæ¶å®¡æ¹ï¼æ°å¢ï¼ |
| | | |
| | | - **POST** `/device/repair/acceptance` |
| | | - 说æï¼ä»
`å¾
éªæ¶(3)` å¯å®¡æ¹ï¼å®¡æ¹éè¿åç¶ææ¹ä¸º `å®ç»(1)`ã |
| | | |
| | | 请æ±åæ°ï¼Bodyï¼ï¼ |
| | | |
| | | | åæ®µ | ç±»å | å¿
å¡« | 说æ | |
| | | |---|---|---|---| |
| | | | `id` | long | æ¯ | æ¥ä¿®è®°å½ID | |
| | | | `acceptanceName` | string | æ¯ | éªæ¶äºº | |
| | | | `acceptanceTime` | string | æ¯ | éªæ¶æ¶é´ï¼æ ¼å¼ `yyyy-MM-dd HH:mm:ss` | |
| | | | `acceptanceRemark` | string | æ¯ | éªæ¶å¤æ³¨ | |
| | | |
| | | 请æ±ç¤ºä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "id": 10001, |
| | | "acceptanceName": "çäº", |
| | | "acceptanceTime": "2026-05-14 11:00:00", |
| | | "acceptanceRemark": "ç»´ä¿®é¡¹æ ¸éªéè¿ï¼è®¾å¤è¿è¡æ£å¸¸" |
| | | } |
| | | ``` |
| | | |
| | | 常è§å¤±è´¥æç¤ºï¼ |
| | | |
| | | - `æ¥ä¿®è®°å½idä¸è½ä¸ºç©º` |
| | | - `æ¥ä¿®è®°å½ä¸åå¨` |
| | | - `该æ¥ä¿®æªè¿å
¥å¾
éªæ¶ç¶æï¼ä¸è½å®¡æ¹` |
| | | - `éªæ¶äººä¸è½ä¸ºç©º` |
| | | - `éªæ¶æ¶é´ä¸è½ä¸ºç©º` |
| | | - `éªæ¶å¤æ³¨ä¸è½ä¸ºç©º` |
| | | |
| | | #### 2.3.3 æ®éæ´æ°æ¥å£éå¶ |
| | | |
| | | - **PUT** `/device/repair` |
| | | - éå¶ï¼ä¸è½éè¿æ®éæ´æ°ç´æ¥æç¶ææ¹æ `å®ç»(1)`ï¼å¿
é¡»èµ°éªæ¶å®¡æ¹æ¥å£ï¼ã |
| | | - 失败æç¤ºï¼`请å
æäº¤éªæ¶å®¡æ¹ï¼éªæ¶éè¿åæå¯å®ç»` |
| | | |
| | | --- |
| | | |
| | | ## 3. è¿ååæ®µåæ´ï¼æ¥ä¿®å表/详æ
ï¼ |
| | | |
| | | 以䏿¥å£è¿åå·²æ°å¢éªæ¶åæ®µï¼ |
| | | |
| | | - **GET** `/device/repair/page` |
| | | - **GET** `/device/repair/{id}` |
| | | |
| | | æ°å¢è¿ååæ®µï¼ |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |---|---|---| |
| | | | `acceptanceName` | string | éªæ¶äºº | |
| | | | `acceptanceTime` | string | éªæ¶æ¶é´ | |
| | | | `acceptanceRemark` | string | éªæ¶å¤æ³¨ | |
| | | |
| | | --- |
| | | |
| | | ## 4. å端æ¹é 建议 |
| | | |
| | | 1. æ¥ä¿®å表å¢å ç¶æå¼ `3=å¾
éªæ¶` çå±ç¤ºææ¡ä¸çé项ã |
| | | 2. â确认维修âæé®è°ç¨ `/device/repair/repair`ï¼æååå·æ°ä¸ºå¾
éªæ¶ç¶æã |
| | | 3. æ°å¢âéªæ¶å®¡æ¹âå¼¹çªï¼å¿
å¡«ï¼ |
| | | - éªæ¶äºº |
| | | - éªæ¶æ¶é´ |
| | | - éªæ¶å¤æ³¨ |
| | | 4. ç¦æ¢å¨æ®éç¼è¾é¡µç´æ¥å°ç¶æç½®ä¸ºå®ç»ã |
| | | 5. 设å¤ä¿å
»å®æ¶ä»»å¡æ°å¢âä¿å
»äººâè¾å
¥é¡¹ï¼å¹¶å¨å表/详æ
å±ç¤ºã |
| | | 6. ç§ç®æ»è´¦é¡µé¢æåè¡å计渲æï¼ä¸åæ¾ç¤ºåè¯åå·ãæè¦åã |
| | | |
| | | --- |
| | | |
| | | ## 5. èè°æ£æ¥æ¸
å |
| | | |
| | | 1. ç§ç®æ»è´¦æ¥è¯¢è¿å `data.length === 1`ï¼ä¸æ `voucherNo/summary`ã |
| | | 2. æ°å¢ä¿å
»å®æ¶ä»»å¡æ¶ä¼ `maintenancePerson`ï¼å表è½åæ¾ã |
| | | 3. 宿¶ä»»å¡è§¦ååï¼çæçä¿å
»è®°å½ `maintenanceActuallyName` ä¸å®æ¶ä»»å¡ä¿å
»äººä¸è´ã |
| | | 4. æ¥ä¿®åæµç¨ï¼`0å¾
ç»´ä¿® -> 3å¾
éªæ¶ -> 1å®ç»`ã |
| | | 5. å¾
éªæ¶åæ®æªå¡«éªæ¶äºº/éªæ¶æ¶é´/éªæ¶å¤æ³¨æ¶ï¼å端è¿å对åºé误æç¤ºã |
| | | 6. å°è¯éè¿ `PUT /device/repair` ç´æ¥è®¾ä¸ºå®ç»æ¶ï¼å端è¿åæ¦æªæç¤ºã |
| | | |
| | | --- |
| | | |
| | | ## 6. æ°æ®åºåæ´ï¼èè°åç¡®è®¤ï¼ |
| | | |
| | | ```sql |
| | | ALTER TABLE maintenance_task |
| | | ADD COLUMN maintenance_person VARCHAR(100) NULL COMMENT 'ä¿å
»äºº'; |
| | | |
| | | ALTER TABLE device_repair |
| | | ADD COLUMN acceptance_name VARCHAR(100) NULL COMMENT 'éªæ¶äºº', |
| | | ADD COLUMN acceptance_time DATETIME NULL COMMENT 'éªæ¶æ¶é´', |
| | | ADD COLUMN acceptance_remark VARCHAR(500) NULL COMMENT 'éªæ¶å¤æ³¨'; |
| | | ``` |
| | | |
| | | > è¥æªæ§è¡ä»¥ä¸ SQLï¼ç¸å
³æ¥å£ä¼åºç°å段ä¸åå¨å¼å¸¸ã |
| | | |
| | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | |
| | | |
| | | @Schema(description = "å¼å§æ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date endDate; |
| | | } |
| | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | |
| | | |
| | | @Schema(description = "å¼å§æ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date endDate; |
| | | } |
| | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | |
| | | |
| | | @Schema(description = "å¼å§æ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date endDate; |
| | | } |
| | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.util.Date; |
| | | |
| | |
| | | |
| | | @Schema(description = "å¼å§æ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date startDate; |
| | | |
| | | @Schema(description = "ç»ææ¥æ") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date endDate; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * ç§ç®æç»è´¦æ¥è¯¢åæ°ï¼å«è¾
婿 ¸ç®æ¡ä»¶ï¼ã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinDetailLedgerQueryDto extends FinLedgerQueryDto { |
| | | |
| | | /** |
| | | * è¾
婿 ¸ç®ç±»åï¼customer/supplier/department/employee/projectã |
| | | */ |
| | | private String auxiliaryType; |
| | | |
| | | /** |
| | | * è¾
婿 ¸ç®å¯¹è±¡IDã |
| | | */ |
| | | private String auxiliaryId; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import com.ruoyi.account.pojo.financial.FinFixedAsset; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * åºå®èµäº§æ¥è¯¢ä¸ä¿å DTOã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinFixedAssetDto extends FinFixedAsset { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æ¹éID请æ±åæ°ã |
| | | */ |
| | | @Data |
| | | public class FinIdBatchDto { |
| | | |
| | | /** |
| | | * IDéåã |
| | | */ |
| | | private List<Long> ids; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import com.ruoyi.account.pojo.financial.FinIntangibleAsset; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§æ¥è¯¢ä¸ä¿å DTOã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinIntangibleAssetDto extends FinIntangibleAsset { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * ç§ç®è´¦æ¥è¯¢åæ°ã |
| | | */ |
| | | @Data |
| | | public class FinLedgerQueryDto { |
| | | |
| | | /** |
| | | * ç§ç®ç¼ç ï¼æ¯ææ«çº§ææå®ç§ç®ï¼ã |
| | | */ |
| | | private String subjectCode; |
| | | |
| | | /** |
| | | * å¼å§æä»½ï¼æ ¼å¼ï¼YYYY-MMã |
| | | */ |
| | | private String startMonth; |
| | | |
| | | /** |
| | | * ç»ææä»½ï¼æ ¼å¼ï¼YYYY-MMã |
| | | */ |
| | | private String endMonth; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * åè¯ä¿å DTOï¼ä¸»è¡¨ + åå½ï¼ã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinVoucherDto extends FinVoucher { |
| | | |
| | | /** |
| | | * åè¯æç»åå½ã |
| | | */ |
| | | private List<FinVoucherEntryDto> entries; |
| | | |
| | | private List<StorageBlobDTO> storageBlobDTOs; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import com.ruoyi.account.pojo.financial.FinVoucherEntry; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * åè¯åå½ DTOã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinVoucherEntryDto extends FinVoucherEntry { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * åè¯å页æ¥è¯¢åæ°ã |
| | | */ |
| | | @Data |
| | | public class FinVoucherPageDto { |
| | | |
| | | /** |
| | | * åè¯åå·ï¼æ¨¡ç³å¹é
ï¼ã |
| | | */ |
| | | private String voucherNo; |
| | | |
| | | /** |
| | | * å¶å人ã |
| | | */ |
| | | private String creator; |
| | | |
| | | /** |
| | | * åè¯ç¶æã |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * å¼å§æ¥æï¼å«ï¼ã |
| | | */ |
| | | private LocalDate startDate; |
| | | |
| | | /** |
| | | * ç»ææ¥æï¼å«ï¼ã |
| | | */ |
| | | private LocalDate endDate; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.dto.financial; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * åè¯ç¶æåæ´åæ°ã |
| | | */ |
| | | @Data |
| | | public class FinVoucherStatusDto { |
| | | |
| | | /** |
| | | * åè¯IDã |
| | | */ |
| | | private Long id; |
| | | } |
| | |
| | | import com.ruoyi.account.pojo.AccountSubject; |
| | | import lombok.Data; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class AccountSubjectVo extends AccountSubject { |
| | | |
| | | /** |
| | | * åç§ç®å表ï¼éå½ç»æï¼ã |
| | | */ |
| | | private List<AccountSubjectVo> children = new ArrayList<>(); |
| | | |
| | | /** |
| | | * æ¯å¦å¶åèç¹ã |
| | | */ |
| | | private Boolean leaf; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.vo.financial; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * ç§ç®è´¦åºç¡å彿¥è¯¢å¯¹è±¡ï¼SQLæ å°ä½¿ç¨ï¼ã |
| | | */ |
| | | @Data |
| | | public class FinLedgerEntryRecordVo { |
| | | |
| | | /** |
| | | * åè¯æ¥æã |
| | | */ |
| | | private LocalDate voucherDate; |
| | | |
| | | /** |
| | | * åè¯åå·ã |
| | | */ |
| | | private String voucherNo; |
| | | |
| | | /** |
| | | * æè¦ã |
| | | */ |
| | | private String summary; |
| | | |
| | | /** |
| | | * åæ¹éé¢ã |
| | | */ |
| | | private BigDecimal debit; |
| | | |
| | | /** |
| | | * è´·æ¹éé¢ã |
| | | */ |
| | | private BigDecimal credit; |
| | | |
| | | /** |
| | | * è¡å·ï¼æåºå段ï¼ã |
| | | */ |
| | | private Integer rowNo; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.vo.financial; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonInclude; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | |
| | | /** |
| | | * ç§ç®è´¦è¡æ°æ®è¿å对象ã |
| | | */ |
| | | @Data |
| | | @JsonInclude(JsonInclude.Include.NON_NULL) |
| | | public class FinLedgerRowVo { |
| | | |
| | | /** |
| | | * è¡ç±»åï¼opening/entry/monthly_total/yearly_totalã |
| | | */ |
| | | private String rowType; |
| | | |
| | | /** |
| | | * æ¥æã |
| | | */ |
| | | private LocalDate date; |
| | | |
| | | /** |
| | | * åè¯åå·ã |
| | | */ |
| | | private String voucherNo; |
| | | |
| | | /** |
| | | * æè¦ã |
| | | */ |
| | | private String summary; |
| | | |
| | | /** |
| | | * åæ¹éé¢ã |
| | | */ |
| | | private BigDecimal debit; |
| | | |
| | | /** |
| | | * è´·æ¹éé¢ã |
| | | */ |
| | | private BigDecimal credit; |
| | | |
| | | /** |
| | | * ä½é¢æ¹åï¼å/è´·ã |
| | | */ |
| | | private String direction; |
| | | |
| | | /** |
| | | * ä½é¢ï¼åæ£è´·è´ï¼ã |
| | | */ |
| | | private BigDecimal balance; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.bean.vo.financial; |
| | | |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | import com.ruoyi.account.pojo.financial.FinVoucherEntry; |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * åè¯è¯¦æ
è¿å对象ã |
| | | */ |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class FinVoucherDetailVo extends FinVoucher { |
| | | |
| | | /** |
| | | * åè¯åå½å表ã |
| | | */ |
| | | private List<FinVoucherEntry> entries; |
| | | private List<StorageBlobVO> storageBlobVOList; |
| | | } |
| | |
| | | |
| | | @GetMapping("/list") |
| | | @Log(title = "æ»è´¦ç§ç®æ°æ®éå", businessType = BusinessType.OTHER) |
| | | @Operation(summary = "æ»è´¦ç§ç®å页æ¥è¯¢") |
| | | @Operation(summary = "æ»è´¦ç§ç®æ å½¢æ¥è¯¢ï¼éå½ï¼") |
| | | public R<IPage<AccountSubjectVo>> AccountSubjectDtoList(Page<AccountSubjectDto> page, AccountSubjectDto accountSubjectDto) { |
| | | IPage<AccountSubjectVo> paramList = accountSubjectService.baseList(page, accountSubjectDto); |
| | | return R.ok(paramList); |
| | |
| | | @Log(title = "æ°å¢æ»è´¦ç§ç®", businessType = BusinessType.INSERT) |
| | | @Operation(summary = "æ°å¢æ»è´¦ç§ç®") |
| | | public R AccountSubjectDtoAdd(@RequestBody AccountSubjectDto accountSubjectDto) { |
| | | return R.ok(accountSubjectService.save(accountSubjectDto)); |
| | | return R.ok(accountSubjectService.saveAccountSubject(accountSubjectDto)); |
| | | } |
| | | |
| | | @PutMapping("/edit") |
| | | @Log(title = "ä¿®æ¹æ»è´¦ç§ç®", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "ä¿®æ¹æ»è´¦ç§ç®") |
| | | public R AccountSubjectDtoEdit(@RequestBody AccountSubjectDto accountSubjectDto) { |
| | | return R.ok(accountSubjectService.updateById(accountSubjectDto)); |
| | | return R.ok(accountSubjectService.updateAccountSubject(accountSubjectDto)); |
| | | } |
| | | |
| | | @DeleteMapping("/remove/{ids}") |
| | | @Log(title = "å 餿»è´¦ç§ç®", businessType = BusinessType.DELETE) |
| | | @Operation(summary = "å 餿»è´¦ç§ç®") |
| | | public R AccountSubjectDtooRemove(@PathVariable Long[] ids) { |
| | | return R.ok(accountSubjectService.removeBatchByIds(Arrays.asList(ids))); |
| | | return R.ok(accountSubjectService.removeAccountSubjectByIds(Arrays.asList(ids))); |
| | | } |
| | | |
| | | @PostMapping("/export") |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.controller.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.bean.dto.financial.FinFixedAssetDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinIdBatchDto; |
| | | import com.ruoyi.account.pojo.financial.FinFixedAsset; |
| | | import com.ruoyi.account.service.financial.FinFixedAssetService; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * åºå®èµäº§æ§å¶å¨ã |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/financial/fixedAsset") |
| | | @RequiredArgsConstructor |
| | | @Tag(name = "è´¢å¡ç®¡ç-åºå®èµäº§") |
| | | public class FinFixedAssetController { |
| | | |
| | | private final FinFixedAssetService finFixedAssetService; |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "åºå®èµäº§å页æ¥è¯¢") |
| | | public R<IPage<FinFixedAsset>> page(Page<FinFixedAsset> page, FinFixedAssetDto queryDto) { |
| | | return R.ok(finFixedAssetService.pageList(page, queryDto)); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | @Log(title = "åºå®èµäº§", businessType = BusinessType.INSERT) |
| | | @Operation(summary = "æ°å¢åºå®èµäº§") |
| | | public R<Boolean> add(@RequestBody FinFixedAssetDto dto) { |
| | | return R.ok(finFixedAssetService.add(dto)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Log(title = "åºå®èµäº§", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "ä¿®æ¹åºå®èµäº§") |
| | | public R<Boolean> update(@RequestBody FinFixedAssetDto dto) { |
| | | return R.ok(finFixedAssetService.update(dto)); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Log(title = "åºå®èµäº§", businessType = BusinessType.DELETE) |
| | | @Operation(summary = "å é¤åºå®èµäº§") |
| | | public R<Boolean> delete(@RequestParam("ids") Long[] ids) { |
| | | return R.ok(finFixedAssetService.deleteByIds(Arrays.asList(ids))); |
| | | } |
| | | |
| | | @PostMapping("/depreciate") |
| | | @Log(title = "åºå®èµäº§ææ§è®¡æ", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "åºå®èµäº§ææè®¡æææ§") |
| | | public R depreciate(@RequestBody(required = false) FinIdBatchDto dto) { |
| | | return R.ok(finFixedAssetService.depreciate(dto == null ? null : dto.getIds())); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.controller.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.bean.dto.financial.FinIdBatchDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinIntangibleAssetDto; |
| | | import com.ruoyi.account.pojo.financial.FinIntangibleAsset; |
| | | import com.ruoyi.account.service.financial.FinIntangibleAssetService; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§æ§å¶å¨ã |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/financial/intangibleAsset") |
| | | @RequiredArgsConstructor |
| | | @Tag(name = "è´¢å¡ç®¡ç-æ å½¢èµäº§") |
| | | public class FinIntangibleAssetController { |
| | | |
| | | private final FinIntangibleAssetService finIntangibleAssetService; |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "æ å½¢èµäº§å页æ¥è¯¢") |
| | | public R<IPage<FinIntangibleAsset>> page(Page<FinIntangibleAsset> page, FinIntangibleAssetDto queryDto) { |
| | | return R.ok(finIntangibleAssetService.pageList(page, queryDto)); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | @Log(title = "æ å½¢èµäº§", businessType = BusinessType.INSERT) |
| | | @Operation(summary = "æ°å¢æ å½¢èµäº§") |
| | | public R<Boolean> add(@RequestBody FinIntangibleAssetDto dto) { |
| | | return R.ok(finIntangibleAssetService.add(dto)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Log(title = "æ å½¢èµäº§", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "ä¿®æ¹æ å½¢èµäº§") |
| | | public R<Boolean> update(@RequestBody FinIntangibleAssetDto dto) { |
| | | return R.ok(finIntangibleAssetService.update(dto)); |
| | | } |
| | | |
| | | @DeleteMapping("/delete") |
| | | @Log(title = "æ å½¢èµäº§", businessType = BusinessType.DELETE) |
| | | @Operation(summary = "å 餿 å½¢èµäº§") |
| | | public R<Boolean> delete(@RequestParam("ids") Long[] ids) { |
| | | return R.ok(finIntangibleAssetService.deleteByIds(Arrays.asList(ids))); |
| | | } |
| | | |
| | | @PostMapping("/amortize") |
| | | @Log(title = "æ å½¢èµäº§æé计æ", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "æ å½¢èµäº§ææè®¡ææé") |
| | | public R amortize(@RequestBody(required = false) FinIdBatchDto dto) { |
| | | return R.ok(finIntangibleAssetService.amortize(dto == null ? null : dto.getIds())); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.controller.financial; |
| | | |
| | | import com.ruoyi.account.bean.dto.financial.FinDetailLedgerQueryDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinLedgerQueryDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinLedgerRowVo; |
| | | import com.ruoyi.account.service.financial.FinLedgerService; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * ç§ç®æ»è´¦/æç»è´¦æ§å¶å¨ã |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/financial/ledger") |
| | | @RequiredArgsConstructor |
| | | @Tag(name = "è´¢å¡ç®¡ç-ç§ç®è´¦") |
| | | public class FinLedgerController { |
| | | |
| | | private final FinLedgerService finLedgerService; |
| | | |
| | | @GetMapping("/general") |
| | | @Operation(summary = "ç§ç®æ»è´¦æ¥è¯¢") |
| | | public R<List<FinLedgerRowVo>> general(FinLedgerQueryDto queryDto) { |
| | | return R.ok(finLedgerService.queryGeneralLedger(queryDto)); |
| | | } |
| | | |
| | | @GetMapping("/detail") |
| | | @Operation(summary = "ç§ç®æç»è´¦æ¥è¯¢") |
| | | public R<List<FinLedgerRowVo>> detail(FinDetailLedgerQueryDto queryDto) { |
| | | return R.ok(finLedgerService.queryDetailLedger(queryDto)); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.controller.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherPageDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherStatusDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinVoucherDetailVo; |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | import com.ruoyi.account.service.financial.FinVoucherService; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | /** |
| | | * åè¯æ§å¶å¨ã |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/financial/voucher") |
| | | @RequiredArgsConstructor |
| | | @Tag(name = "è´¢å¡ç®¡ç-åè¯") |
| | | public class FinVoucherController { |
| | | |
| | | private final FinVoucherService finVoucherService; |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "åè¯å页æ¥è¯¢") |
| | | public R<IPage<FinVoucher>> page(Page<FinVoucher> page, FinVoucherPageDto queryDto) { |
| | | return R.ok(finVoucherService.pageList(page, queryDto)); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | @Log(title = "åè¯", businessType = BusinessType.INSERT) |
| | | @Operation(summary = "æ°å¢åè¯") |
| | | public R<Boolean> add(@RequestBody FinVoucherDto dto) { |
| | | return R.ok(finVoucherService.addVoucher(dto)); |
| | | } |
| | | |
| | | @PutMapping("/update") |
| | | @Log(title = "åè¯", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "ä¿®æ¹åè¯") |
| | | public R<Boolean> update(@RequestBody FinVoucherDto dto) { |
| | | return R.ok(finVoucherService.updateVoucher(dto)); |
| | | } |
| | | |
| | | @PostMapping("/post") |
| | | @Log(title = "åè¯è¿è´¦", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "åè¯è¿è´¦") |
| | | public R<Boolean> post(@RequestBody FinVoucherStatusDto dto) { |
| | | return R.ok(finVoucherService.postVoucher(dto.getId())); |
| | | } |
| | | |
| | | @PostMapping("/cancel") |
| | | @Log(title = "åè¯ä½åº", businessType = BusinessType.UPDATE) |
| | | @Operation(summary = "åè¯ä½åº") |
| | | public R<Boolean> cancel(@RequestBody FinVoucherStatusDto dto) { |
| | | return R.ok(finVoucherService.cancelVoucher(dto.getId())); |
| | | } |
| | | |
| | | @GetMapping("/detail/{id}") |
| | | @Operation(summary = "åè¯è¯¦æ
") |
| | | public R<FinVoucherDetailVo> detail(@PathVariable("id") Long id) { |
| | | return R.ok(finVoucherService.detail(id)); |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.account.pojo.AccountSubject; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Mapper |
| | | public interface AccountSubjectMapper extends BaseMapper<AccountSubject> { |
| | | |
| | | Long countReferencedBySubjectCodes(@Param("subjectCodes") List<String> subjectCodes); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.mapper.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.account.pojo.financial.FinFixedAsset; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * åºå®èµäº§ Mapperã |
| | | */ |
| | | @Mapper |
| | | public interface FinFixedAssetMapper extends BaseMapper<FinFixedAsset> { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.mapper.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.account.pojo.financial.FinIntangibleAsset; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§ Mapperã |
| | | */ |
| | | @Mapper |
| | | public interface FinIntangibleAssetMapper extends BaseMapper<FinIntangibleAsset> { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.mapper.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.account.bean.vo.financial.FinLedgerEntryRecordVo; |
| | | import com.ruoyi.account.pojo.financial.FinVoucherEntry; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * åè¯åå½ Mapperã |
| | | */ |
| | | @Mapper |
| | | public interface FinVoucherEntryMapper extends BaseMapper<FinVoucherEntry> { |
| | | |
| | | List<FinLedgerEntryRecordVo> listPostedEntries(@Param("subjectCode") String subjectCode, |
| | | @Param("startDate") LocalDate startDate, |
| | | @Param("endDate") LocalDate endDate, |
| | | @Param("auxiliaryType") String auxiliaryType, |
| | | @Param("auxiliaryId") String auxiliaryId); |
| | | |
| | | List<FinLedgerEntryRecordVo> listPostedEntriesBefore(@Param("subjectCode") String subjectCode, |
| | | @Param("beforeDate") LocalDate beforeDate, |
| | | @Param("auxiliaryType") String auxiliaryType, |
| | | @Param("auxiliaryId") String auxiliaryId); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.mapper.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * åè¯ä¸»è¡¨ Mapperã |
| | | */ |
| | | @Mapper |
| | | public interface FinVoucherMapper extends BaseMapper<FinVoucher> { |
| | | } |
| | |
| | | private Long id; |
| | | |
| | | /** |
| | | * ç¶ç§ç®IDï¼ä¸ºç©ºè¡¨ç¤ºæ ¹èç¹ï¼ |
| | | */ |
| | | @ApiModelProperty("ç¶ç§ç®IDï¼ä¸ºç©ºè¡¨ç¤ºæ ¹èç¹ï¼") |
| | | private Long parentId; |
| | | |
| | | /** |
| | | * ç§ç®ç¼ç (å¯ä¸æ è¯) |
| | | */ |
| | | @ApiModelProperty("ç§ç®ç¼ç (å¯ä¸æ è¯)") |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.pojo.financial; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import lombok.ToString; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * åºå®èµäº§å®ä½ã |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ToString |
| | | @TableName("fin_fixed_asset") |
| | | @ApiModel(value = "FinFixedAsset对象", description = "åºå®èµäº§") |
| | | public class FinFixedAsset implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty("主é®ID") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("èµäº§ç¼å·") |
| | | private String assetCode; |
| | | |
| | | @ApiModelProperty("èµäº§åç§°") |
| | | private String assetName; |
| | | |
| | | @ApiModelProperty("èµäº§ç±»å«") |
| | | private String category; |
| | | |
| | | @ApiModelProperty("è§æ ¼åå·") |
| | | private String specification; |
| | | |
| | | @ApiModelProperty("è´ç½®æ¥æ") |
| | | private LocalDate purchaseDate; |
| | | |
| | | @ApiModelProperty("èµäº§åå¼") |
| | | private BigDecimal originalValue; |
| | | |
| | | @ApiModelProperty("使ç¨å¹´é(å¹´)") |
| | | private Integer usefulLife; |
| | | |
| | | @ApiModelProperty("æ®å¼ç(%)") |
| | | private BigDecimal residualRate; |
| | | |
| | | @ApiModelProperty("ç´¯è®¡ææ§") |
| | | private BigDecimal accumulatedDepreciation; |
| | | |
| | | @ApiModelProperty("åå¼") |
| | | private BigDecimal netValue; |
| | | |
| | | @ApiModelProperty("åæ¾å°ç¹") |
| | | private String location; |
| | | |
| | | @ApiModelProperty("使ç¨é¨é¨") |
| | | private String department; |
| | | |
| | | @ApiModelProperty("ä¿ç®¡äºº") |
| | | private String keeper; |
| | | |
| | | @ApiModelProperty("ç¶æ") |
| | | private String status; |
| | | |
| | | @ApiModelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | @ApiModelProperty("å建人") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private String createUser; |
| | | |
| | | @ApiModelProperty("å建æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹äºº") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private String updateUser; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @ApiModelProperty("é¨é¨ID") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.pojo.financial; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import lombok.ToString; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§å®ä½ã |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ToString |
| | | @TableName("fin_intangible_asset") |
| | | @ApiModel(value = "FinIntangibleAsset对象", description = "æ å½¢èµäº§") |
| | | public class FinIntangibleAsset implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty("主é®ID") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("èµäº§ç¼å·") |
| | | private String assetCode; |
| | | |
| | | @ApiModelProperty("èµäº§åç§°") |
| | | private String assetName; |
| | | |
| | | @ApiModelProperty("èµäº§ç±»å«") |
| | | private String category; |
| | | |
| | | @ApiModelProperty("è¯ä¹¦ç¼å·") |
| | | private String certificateNo; |
| | | |
| | | @ApiModelProperty("å徿¥æ") |
| | | private LocalDate acquisitionDate; |
| | | |
| | | @ApiModelProperty("èµäº§åå¼") |
| | | private BigDecimal originalValue; |
| | | |
| | | @ApiModelProperty("æéå¹´é(å¹´)") |
| | | private Integer amortizationPeriod; |
| | | |
| | | @ApiModelProperty("æ®å¼ç(%)") |
| | | private BigDecimal residualRate; |
| | | |
| | | @ApiModelProperty("累计æé") |
| | | private BigDecimal accumulatedAmortization; |
| | | |
| | | @ApiModelProperty("åå¼") |
| | | private BigDecimal netValue; |
| | | |
| | | @ApiModelProperty("æææè³") |
| | | private LocalDate validityDate; |
| | | |
| | | @ApiModelProperty("ç¶æ") |
| | | private String status; |
| | | |
| | | @ApiModelProperty("èµäº§æè¿°") |
| | | private String description; |
| | | |
| | | @ApiModelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | @ApiModelProperty("å建人") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private String createUser; |
| | | |
| | | @ApiModelProperty("å建æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹äºº") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private String updateUser; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @ApiModelProperty("é¨é¨ID") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.pojo.financial; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import lombok.ToString; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * åè¯ä¸»è¡¨å®ä½ã |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ToString |
| | | @TableName("fin_voucher") |
| | | @ApiModel(value = "FinVoucher对象", description = "åè¯ä¸»è¡¨") |
| | | public class FinVoucher implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty("主é®ID") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("åè¯åå·") |
| | | private String voucherNo; |
| | | |
| | | @ApiModelProperty("åè¯æ¥æ") |
| | | private LocalDate voucherDate; |
| | | |
| | | @ApiModelProperty("æè¦") |
| | | private String summary; |
| | | |
| | | @ApiModelProperty("åæ¹å计") |
| | | private BigDecimal debit; |
| | | |
| | | @ApiModelProperty("è´·æ¹å计") |
| | | private BigDecimal credit; |
| | | |
| | | @ApiModelProperty("å¶å人") |
| | | private String creator; |
| | | |
| | | @ApiModelProperty("ç¶æ: unposted/posted/cancelled") |
| | | private String status; |
| | | |
| | | @ApiModelProperty("éä»¶æ°é") |
| | | private Integer attachmentCount; |
| | | |
| | | @ApiModelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | @ApiModelProperty("å建人") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private String createUser; |
| | | |
| | | @ApiModelProperty("å建æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹äºº") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private String updateUser; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @ApiModelProperty("é¨é¨ID") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.pojo.financial; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import lombok.ToString; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * åè¯åå½å®ä½ã |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ToString |
| | | @TableName("fin_voucher_entry") |
| | | @ApiModel(value = "FinVoucherEntry对象", description = "åè¯åå½") |
| | | public class FinVoucherEntry implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty("主é®ID") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("åè¯ID") |
| | | private Long voucherId; |
| | | |
| | | @ApiModelProperty("è¡å·") |
| | | private Integer rowNo; |
| | | |
| | | @ApiModelProperty("ç§ç®ç¼ç ") |
| | | private String subjectCode; |
| | | |
| | | @ApiModelProperty("ç§ç®åç§°") |
| | | private String subjectName; |
| | | |
| | | @ApiModelProperty("æè¦") |
| | | private String summary; |
| | | |
| | | @ApiModelProperty("åæ¹éé¢") |
| | | private BigDecimal debit; |
| | | |
| | | @ApiModelProperty("è´·æ¹éé¢") |
| | | private BigDecimal credit; |
| | | |
| | | @ApiModelProperty("è¾
婿 ¸ç®ç±»å") |
| | | private String auxiliaryType; |
| | | |
| | | @ApiModelProperty("è¾
婿 ¸ç®å¯¹è±¡ID") |
| | | private String auxiliaryId; |
| | | |
| | | @ApiModelProperty("è¾
婿 ¸ç®å¯¹è±¡åç§°") |
| | | private String auxiliaryName; |
| | | |
| | | @ApiModelProperty("å建人") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private String createUser; |
| | | |
| | | @ApiModelProperty("å建æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹äºº") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private String updateUser; |
| | | |
| | | @ApiModelProperty("ä¿®æ¹æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @ApiModelProperty("é¨é¨ID") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * æ»è´¦ç§ç®è¡¨ æå¡ç±» |
| | |
| | | |
| | | IPage<AccountSubjectVo> baseList(Page<AccountSubjectDto> page, AccountSubjectDto accountSubjectDto); |
| | | |
| | | Boolean saveAccountSubject(AccountSubjectDto accountSubjectDto); |
| | | |
| | | Boolean updateAccountSubject(AccountSubjectDto accountSubjectDto); |
| | | |
| | | Boolean removeAccountSubjectByIds(List<Long> ids); |
| | | |
| | | void exportAccountSubject(HttpServletResponse response); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.account.bean.dto.financial.FinFixedAssetDto; |
| | | import com.ruoyi.account.pojo.financial.FinFixedAsset; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * åºå®èµäº§æå¡ã |
| | | */ |
| | | public interface FinFixedAssetService extends IService<FinFixedAsset> { |
| | | |
| | | IPage<FinFixedAsset> pageList(Page<FinFixedAsset> page, FinFixedAssetDto queryDto); |
| | | |
| | | Boolean add(FinFixedAssetDto dto); |
| | | |
| | | Boolean update(FinFixedAssetDto dto); |
| | | |
| | | Boolean deleteByIds(List<Long> ids); |
| | | |
| | | Map<String, Object> depreciate(List<Long> ids); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.account.bean.dto.financial.FinIntangibleAssetDto; |
| | | import com.ruoyi.account.pojo.financial.FinIntangibleAsset; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§æå¡ã |
| | | */ |
| | | public interface FinIntangibleAssetService extends IService<FinIntangibleAsset> { |
| | | |
| | | IPage<FinIntangibleAsset> pageList(Page<FinIntangibleAsset> page, FinIntangibleAssetDto queryDto); |
| | | |
| | | Boolean add(FinIntangibleAssetDto dto); |
| | | |
| | | Boolean update(FinIntangibleAssetDto dto); |
| | | |
| | | Boolean deleteByIds(List<Long> ids); |
| | | |
| | | Map<String, Object> amortize(List<Long> ids); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.financial; |
| | | |
| | | import com.ruoyi.account.bean.dto.financial.FinDetailLedgerQueryDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinLedgerQueryDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinLedgerRowVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * ç§ç®è´¦æå¡ã |
| | | */ |
| | | public interface FinLedgerService { |
| | | |
| | | List<FinLedgerRowVo> queryGeneralLedger(FinLedgerQueryDto queryDto); |
| | | |
| | | List<FinLedgerRowVo> queryDetailLedger(FinDetailLedgerQueryDto queryDto); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherPageDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinVoucherDetailVo; |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | |
| | | /** |
| | | * åè¯æå¡ã |
| | | */ |
| | | public interface FinVoucherService extends IService<FinVoucher> { |
| | | |
| | | IPage<FinVoucher> pageList(Page<FinVoucher> page, FinVoucherPageDto queryDto); |
| | | |
| | | Boolean addVoucher(FinVoucherDto dto); |
| | | |
| | | Boolean updateVoucher(FinVoucherDto dto); |
| | | |
| | | Boolean postVoucher(Long id); |
| | | |
| | | Boolean cancelVoucher(Long id); |
| | | |
| | | FinVoucherDetailVo detail(Long id); |
| | | } |
| | |
| | | import com.ruoyi.account.mapper.AccountSubjectMapper; |
| | | import com.ruoyi.account.pojo.AccountSubject; |
| | | import com.ruoyi.account.service.AccountSubjectService; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | @Override |
| | | public IPage<AccountSubjectVo> baseList(Page<AccountSubjectDto> page, AccountSubjectDto accountSubjectDto) { |
| | | LambdaQueryWrapper<AccountSubject> queryWrapper = new LambdaQueryWrapper<>(); |
| | | if (accountSubjectDto != null && StringUtils.isNotEmpty(accountSubjectDto.getSubjectCode())) { |
| | | queryWrapper.like(AccountSubject::getSubjectCode, accountSubjectDto.getSubjectCode()); |
| | | } |
| | | if (accountSubjectDto != null && StringUtils.isNotEmpty(accountSubjectDto.getSubjectName())) { |
| | | queryWrapper.like(AccountSubject::getSubjectName, accountSubjectDto.getSubjectName()); |
| | | } |
| | | if (accountSubjectDto != null && StringUtils.isNotEmpty(accountSubjectDto.getSubjectType())) { |
| | | queryWrapper.eq(AccountSubject::getSubjectType, accountSubjectDto.getSubjectType()); |
| | | } |
| | | queryWrapper.orderByDesc(AccountSubject::getId); |
| | | Page<AccountSubjectDto> requestPage = page == null ? new Page<>(1, 10) : page; |
| | | List<AccountSubject> allSubjects = list(loadBaseQueryWrapper(accountSubjectDto)); |
| | | List<AccountSubject> filteredSubjects = applyTreeFilter(allSubjects, accountSubjectDto); |
| | | List<AccountSubjectVo> fullTree = buildTree(filteredSubjects); |
| | | |
| | | Page<AccountSubject> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); |
| | | Page<AccountSubject> paramPage = page(entityPage, queryWrapper); |
| | | long current = requestPage.getCurrent() <= 0 ? 1 : requestPage.getCurrent(); |
| | | long size = requestPage.getSize() <= 0 ? 10 : requestPage.getSize(); |
| | | int fromIndex = (int) Math.min((current - 1) * size, fullTree.size()); |
| | | int toIndex = (int) Math.min(fromIndex + size, fullTree.size()); |
| | | List<AccountSubjectVo> pagedRoots = fromIndex >= toIndex |
| | | ? Collections.emptyList() |
| | | : fullTree.subList(fromIndex, toIndex); |
| | | |
| | | Page<AccountSubjectVo> resultPage = new Page<>(paramPage.getCurrent(), paramPage.getSize(), paramPage.getTotal()); |
| | | List<AccountSubjectVo> records = new ArrayList<>(paramPage.getRecords().size()); |
| | | for (AccountSubject item : paramPage.getRecords()) { |
| | | AccountSubjectVo vo = new AccountSubjectVo(); |
| | | BeanUtils.copyProperties(item, vo); |
| | | records.add(vo); |
| | | } |
| | | resultPage.setRecords(records); |
| | | Page<AccountSubjectVo> resultPage = new Page<>(current, size, fullTree.size()); |
| | | resultPage.setRecords(pagedRoots); |
| | | return resultPage; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean saveAccountSubject(AccountSubjectDto accountSubjectDto) { |
| | | validateSubjectRequiredFields(accountSubjectDto); |
| | | validateSubjectCodeUnique(accountSubjectDto, false); |
| | | validateParent(accountSubjectDto.getParentId(), null); |
| | | if (accountSubjectDto.getStatus() == null) { |
| | | accountSubjectDto.setStatus(0); |
| | | } |
| | | return save(accountSubjectDto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean updateAccountSubject(AccountSubjectDto accountSubjectDto) { |
| | | if (accountSubjectDto == null || accountSubjectDto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼ç§ç®IDä¸è½ä¸ºç©º"); |
| | | } |
| | | if (getById(accountSubjectDto.getId()) == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼æªæ¾å°å¯¹åºç§ç®"); |
| | | } |
| | | validateParent(accountSubjectDto.getParentId(), accountSubjectDto.getId()); |
| | | validateSubjectRequiredFields(accountSubjectDto); |
| | | validateSubjectCodeUnique(accountSubjectDto, true); |
| | | return updateById(accountSubjectDto); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean removeAccountSubjectByIds(List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | return true; |
| | | } |
| | | List<AccountSubject> allSubjects = list(); |
| | | if (allSubjects == null || allSubjects.isEmpty()) { |
| | | return true; |
| | | } |
| | | Map<Long, List<Long>> childrenIdMap = buildChildrenIdMap(allSubjects); |
| | | Set<Long> removeIds = new LinkedHashSet<>(); |
| | | for (Long id : ids) { |
| | | collectDescendantIds(id, childrenIdMap, removeIds); |
| | | } |
| | | if (removeIds.isEmpty()) { |
| | | return true; |
| | | } |
| | | List<String> subjectCodes = allSubjects.stream() |
| | | .filter(subject -> removeIds.contains(subject.getId())) |
| | | .map(AccountSubject::getSubjectCode) |
| | | .filter(StringUtils::isNotEmpty) |
| | | .collect(Collectors.toList()); |
| | | if (!subjectCodes.isEmpty()) { |
| | | Long referencedCount = accountSubjectMapper.countReferencedBySubjectCodes(subjectCodes); |
| | | if (referencedCount != null && referencedCount > 0) { |
| | | throw new ServiceException("å é¤å¤±è´¥ï¼ç§ç®å·²è¢«åè¯åå½å¼ç¨"); |
| | | } |
| | | } |
| | | return removeByIds(removeIds); |
| | | } |
| | | |
| | | @Override |
| | |
| | | ExcelUtil<AccountSubjectImportDto> util = new ExcelUtil<>(AccountSubjectImportDto.class); |
| | | util.exportExcel(response, importDtos , "æ»è´¦ç§ç®"); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªç§ç®å¿
å¡«åæ®µï¼é¿å
èæ°æ®åå
¥ã |
| | | */ |
| | | private void validateSubjectRequiredFields(AccountSubjectDto accountSubjectDto) { |
| | | if (accountSubjectDto == null) { |
| | | throw new ServiceException("æ»è´¦ç§ç®æ°æ®ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(accountSubjectDto.getSubjectCode())) { |
| | | throw new ServiceException("ç§ç®ç¼ç ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(accountSubjectDto.getSubjectName())) { |
| | | throw new ServiceException("ç§ç®åç§°ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(accountSubjectDto.getSubjectType())) { |
| | | throw new ServiceException("ç§ç®ç±»åä¸è½ä¸ºç©º"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªç§ç®ç¼ç å¯ä¸ï¼æ°å¢åä¿®æ¹é½è¦æ§è¡ã |
| | | */ |
| | | private void validateSubjectCodeUnique(AccountSubjectDto accountSubjectDto, boolean isUpdate) { |
| | | LambdaQueryWrapper<AccountSubject> codeQueryWrapper = new LambdaQueryWrapper<>(); |
| | | codeQueryWrapper.eq(AccountSubject::getSubjectCode, accountSubjectDto.getSubjectCode()); |
| | | if (isUpdate) { |
| | | codeQueryWrapper.ne(AccountSubject::getId, accountSubjectDto.getId()); |
| | | } |
| | | AccountSubject exists = getOne(codeQueryWrapper, false); |
| | | if (Objects.nonNull(exists)) { |
| | | throw new ServiceException("ç§ç®ç¼ç å·²åå¨ï¼è¯·å¿éå¤æäº¤"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ä»
æéç¨è¿æ»¤æ¡ä»¶æ¥è¯¢åºç¡æ°æ®ï¼æ å½¢è¿æ»¤åç»ååï¼ã |
| | | */ |
| | | private LambdaQueryWrapper<AccountSubject> loadBaseQueryWrapper(AccountSubjectDto accountSubjectDto) { |
| | | LambdaQueryWrapper<AccountSubject> queryWrapper = new LambdaQueryWrapper<>(); |
| | | if (accountSubjectDto != null && accountSubjectDto.getStatus() != null) { |
| | | queryWrapper.eq(AccountSubject::getStatus, accountSubjectDto.getStatus()); |
| | | } |
| | | queryWrapper.orderByAsc(AccountSubject::getSubjectCode).orderByAsc(AccountSubject::getId); |
| | | return queryWrapper; |
| | | } |
| | | |
| | | /** |
| | | * æ å½¢è¿æ»¤ï¼å½ä¸èç¹åä¿çå
¶ç¶é¾ä¸åæ ï¼ä¿è¯éå½ç»æå®æ´ã |
| | | */ |
| | | private List<AccountSubject> applyTreeFilter(List<AccountSubject> allSubjects, AccountSubjectDto queryDto) { |
| | | if (allSubjects == null || allSubjects.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | boolean hasFilter = queryDto != null && ( |
| | | StringUtils.isNotEmpty(queryDto.getSubjectCode()) |
| | | || StringUtils.isNotEmpty(queryDto.getSubjectName()) |
| | | || StringUtils.isNotEmpty(queryDto.getSubjectType()) |
| | | ); |
| | | if (!hasFilter) { |
| | | return allSubjects; |
| | | } |
| | | |
| | | Map<Long, AccountSubject> subjectMap = allSubjects.stream() |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(AccountSubject::getId, item -> item, (a, b) -> a, LinkedHashMap::new)); |
| | | Map<Long, List<AccountSubject>> childrenMap = buildChildrenMap(allSubjects); |
| | | |
| | | Set<Long> matchedIds = new LinkedHashSet<>(); |
| | | for (AccountSubject subject : allSubjects) { |
| | | if (subject.getId() == null) { |
| | | continue; |
| | | } |
| | | if (matchesFilter(subject, queryDto)) { |
| | | matchedIds.add(subject.getId()); |
| | | } |
| | | } |
| | | if (matchedIds.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | Set<Long> resultIds = new LinkedHashSet<>(matchedIds); |
| | | for (Long matchedId : matchedIds) { |
| | | addAncestors(matchedId, subjectMap, resultIds); |
| | | addDescendants(matchedId, childrenMap, resultIds); |
| | | } |
| | | |
| | | return allSubjects.stream() |
| | | .filter(item -> item.getId() != null && resultIds.contains(item.getId())) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | private boolean matchesFilter(AccountSubject subject, AccountSubjectDto queryDto) { |
| | | if (queryDto == null) { |
| | | return true; |
| | | } |
| | | if (StringUtils.isNotEmpty(queryDto.getSubjectCode()) |
| | | && (subject.getSubjectCode() == null || !subject.getSubjectCode().contains(queryDto.getSubjectCode()))) { |
| | | return false; |
| | | } |
| | | if (StringUtils.isNotEmpty(queryDto.getSubjectName()) |
| | | && (subject.getSubjectName() == null || !subject.getSubjectName().contains(queryDto.getSubjectName()))) { |
| | | return false; |
| | | } |
| | | if (StringUtils.isNotEmpty(queryDto.getSubjectType()) |
| | | && !queryDto.getSubjectType().equals(subject.getSubjectType())) { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private void addAncestors(Long subjectId, Map<Long, AccountSubject> subjectMap, Set<Long> resultIds) { |
| | | AccountSubject current = subjectMap.get(subjectId); |
| | | if (current == null) { |
| | | return; |
| | | } |
| | | Long parentId = current.getParentId(); |
| | | while (parentId != null && parentId > 0) { |
| | | AccountSubject parent = subjectMap.get(parentId); |
| | | if (parent == null) { |
| | | break; |
| | | } |
| | | if (!resultIds.add(parent.getId())) { |
| | | break; |
| | | } |
| | | parentId = parent.getParentId(); |
| | | } |
| | | } |
| | | |
| | | private void addDescendants(Long subjectId, Map<Long, List<AccountSubject>> childrenMap, Set<Long> resultIds) { |
| | | List<AccountSubject> children = childrenMap.getOrDefault(subjectId, Collections.emptyList()); |
| | | for (AccountSubject child : children) { |
| | | if (child.getId() == null) { |
| | | continue; |
| | | } |
| | | if (resultIds.add(child.getId())) { |
| | | addDescendants(child.getId(), childrenMap, resultIds); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private Map<Long, List<AccountSubject>> buildChildrenMap(List<AccountSubject> subjects) { |
| | | Map<Long, List<AccountSubject>> childrenMap = new HashMap<>(); |
| | | for (AccountSubject subject : subjects) { |
| | | if (subject.getId() == null) { |
| | | continue; |
| | | } |
| | | Long parentId = subject.getParentId(); |
| | | if (parentId == null || parentId <= 0) { |
| | | continue; |
| | | } |
| | | childrenMap.computeIfAbsent(parentId, key -> new ArrayList<>()).add(subject); |
| | | } |
| | | return childrenMap; |
| | | } |
| | | |
| | | /** |
| | | * åºäº parentId éå½æå»ºç§ç®æ ã |
| | | */ |
| | | private List<AccountSubjectVo> buildTree(List<AccountSubject> subjects) { |
| | | if (subjects == null || subjects.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<AccountSubject> sortedSubjects = new ArrayList<>(subjects); |
| | | sortedSubjects.sort(Comparator |
| | | .comparing(AccountSubject::getSubjectCode, Comparator.nullsLast(String::compareTo)) |
| | | .thenComparing(AccountSubject::getId, Comparator.nullsLast(Long::compareTo))); |
| | | |
| | | Map<Long, AccountSubjectVo> subjectVoMap = new LinkedHashMap<>(); |
| | | for (AccountSubject subject : sortedSubjects) { |
| | | if (subject.getId() == null) { |
| | | continue; |
| | | } |
| | | AccountSubjectVo vo = new AccountSubjectVo(); |
| | | BeanUtils.copyProperties(subject, vo); |
| | | subjectVoMap.put(subject.getId(), vo); |
| | | } |
| | | |
| | | List<AccountSubjectVo> roots = new ArrayList<>(); |
| | | for (AccountSubject subject : sortedSubjects) { |
| | | if (subject.getId() == null) { |
| | | continue; |
| | | } |
| | | AccountSubjectVo current = subjectVoMap.get(subject.getId()); |
| | | Long parentId = subject.getParentId(); |
| | | if (parentId != null && parentId > 0 && subjectVoMap.containsKey(parentId)) { |
| | | subjectVoMap.get(parentId).getChildren().add(current); |
| | | } else { |
| | | roots.add(current); |
| | | } |
| | | } |
| | | |
| | | markLeafRecursively(roots); |
| | | return roots; |
| | | } |
| | | |
| | | private void markLeafRecursively(List<AccountSubjectVo> nodes) { |
| | | for (AccountSubjectVo node : nodes) { |
| | | List<AccountSubjectVo> children = node.getChildren(); |
| | | node.setLeaf(children == null || children.isEmpty()); |
| | | if (children != null && !children.isEmpty()) { |
| | | markLeafRecursively(children); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªç¶åå
³ç³»ï¼ç¶èç¹å¿
é¡»åå¨ï¼ä¸ä¸è½å½¢æå¾ªç¯å¼ç¨ã |
| | | */ |
| | | private void validateParent(Long parentId, Long currentId) { |
| | | if (parentId == null || parentId <= 0) { |
| | | return; |
| | | } |
| | | if (currentId != null && parentId.equals(currentId)) { |
| | | throw new ServiceException("ç¶ç§ç®ä¸è½éæ©èªèº«"); |
| | | } |
| | | AccountSubject parent = getById(parentId); |
| | | if (parent == null) { |
| | | throw new ServiceException("ç¶ç§ç®ä¸åå¨ï¼è¯·éæ°éæ©"); |
| | | } |
| | | // 鲿¢å½¢æç¯ï¼æ´æ°æ¶ï¼ç¶èç¹ä¸è½æ¯å½åèç¹çä»»æååèç¹ã |
| | | if (currentId != null) { |
| | | Set<Long> visited = new HashSet<>(); |
| | | Long traceParentId = parentId; |
| | | while (traceParentId != null && traceParentId > 0) { |
| | | if (!visited.add(traceParentId)) { |
| | | throw new ServiceException("ç§ç®å±çº§åå¨å¾ªç¯å¼ç¨ï¼è¯·æ£æ¥ç¶ç§ç®è®¾ç½®"); |
| | | } |
| | | if (traceParentId.equals(currentId)) { |
| | | throw new ServiceException("ç¶ç§ç®ä¸è½æ¯å½åç§ç®æå
¶åç§ç®"); |
| | | } |
| | | AccountSubject traceNode = getById(traceParentId); |
| | | if (traceNode == null) { |
| | | break; |
| | | } |
| | | traceParentId = traceNode.getParentId(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private Map<Long, List<Long>> buildChildrenIdMap(List<AccountSubject> subjects) { |
| | | Map<Long, List<Long>> map = new HashMap<>(); |
| | | for (AccountSubject subject : subjects) { |
| | | if (subject.getId() == null || subject.getParentId() == null || subject.getParentId() <= 0) { |
| | | continue; |
| | | } |
| | | map.computeIfAbsent(subject.getParentId(), key -> new ArrayList<>()).add(subject.getId()); |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * æ¶éå¾
å é¤èç¹åå
¶ææååèç¹ã |
| | | */ |
| | | private void collectDescendantIds(Long id, Map<Long, List<Long>> childrenIdMap, Set<Long> result) { |
| | | if (id == null || !result.add(id)) { |
| | | return; |
| | | } |
| | | List<Long> children = childrenIdMap.getOrDefault(id, Collections.emptyList()); |
| | | for (Long childId : children) { |
| | | collectDescendantIds(childId, childrenIdMap, result); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.impl.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.bean.dto.financial.FinFixedAssetDto; |
| | | import com.ruoyi.account.mapper.financial.FinFixedAssetMapper; |
| | | import com.ruoyi.account.pojo.financial.FinFixedAsset; |
| | | import com.ruoyi.account.service.financial.FinFixedAssetService; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * åºå®èµäº§æå¡å®ç°ã |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class FinFixedAssetServiceImpl extends ServiceImpl<FinFixedAssetMapper, FinFixedAsset> implements FinFixedAssetService { |
| | | |
| | | private static final BigDecimal ONE_HUNDRED = new BigDecimal("100"); |
| | | private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); |
| | | private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); |
| | | |
| | | @Override |
| | | public IPage<FinFixedAsset> pageList(Page<FinFixedAsset> page, FinFixedAssetDto queryDto) { |
| | | LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetCode())) { |
| | | wrapper.like(FinFixedAsset::getAssetCode, queryDto.getAssetCode()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetName())) { |
| | | wrapper.like(FinFixedAsset::getAssetName, queryDto.getAssetName()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getCategory())) { |
| | | wrapper.eq(FinFixedAsset::getCategory, queryDto.getCategory()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getStatus())) { |
| | | wrapper.eq(FinFixedAsset::getStatus, queryDto.getStatus()); |
| | | } |
| | | wrapper.orderByDesc(FinFixedAsset::getId); |
| | | return page(page, wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean add(FinFixedAssetDto dto) { |
| | | validateForSave(dto, false); |
| | | if (StringUtils.isEmpty(dto.getAssetCode())) { |
| | | dto.setAssetCode(generateAssetCode()); |
| | | } |
| | | BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate()); |
| | | dto.setResidualRate(residualRate); |
| | | BigDecimal accumulatedDepreciation = defaultMoney(dto.getAccumulatedDepreciation()); |
| | | dto.setAccumulatedDepreciation(accumulatedDepreciation); |
| | | dto.setNetValue(calculateNetValue(dto.getOriginalValue(), accumulatedDepreciation)); |
| | | if (StringUtils.isEmpty(dto.getStatus())) { |
| | | dto.setStatus("in_use"); |
| | | } |
| | | return save(dto); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean update(FinFixedAssetDto dto) { |
| | | if (dto == null || dto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼èµäº§IDä¸è½ä¸ºç©º"); |
| | | } |
| | | FinFixedAsset existed = getById(dto.getId()); |
| | | if (existed == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼åºå®èµäº§ä¸åå¨"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getAssetCode())) { |
| | | dto.setAssetCode(existed.getAssetCode()); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getStatus())) { |
| | | dto.setStatus(existed.getStatus()); |
| | | } |
| | | validateForSave(dto, true); |
| | | BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate()); |
| | | dto.setResidualRate(residualRate); |
| | | if (dto.getAccumulatedDepreciation() == null) { |
| | | dto.setAccumulatedDepreciation(defaultMoney(existed.getAccumulatedDepreciation())); |
| | | } |
| | | dto.setNetValue(calculateNetValue(dto.getOriginalValue(), dto.getAccumulatedDepreciation())); |
| | | return updateById(dto); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean deleteByIds(List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | throw new ServiceException("å é¤å¤±è´¥ï¼è¯·éæ©è¦å é¤çæ°æ®"); |
| | | } |
| | | return removeByIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Map<String, Object> depreciate(List<Long> ids) { |
| | | LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | if (ids != null && !ids.isEmpty()) { |
| | | wrapper.in(FinFixedAsset::getId, ids); |
| | | } else { |
| | | wrapper.eq(FinFixedAsset::getStatus, "in_use"); |
| | | } |
| | | List<FinFixedAsset> assets = list(wrapper); |
| | | BigDecimal totalMonthlyDepreciation = ZERO; |
| | | int processedCount = 0; |
| | | for (FinFixedAsset asset : assets) { |
| | | if (!"in_use".equals(asset.getStatus())) { |
| | | continue; |
| | | } |
| | | BigDecimal monthlyDepreciation = calculateMonthlyDepreciation( |
| | | asset.getOriginalValue(), |
| | | asset.getResidualRate(), |
| | | asset.getUsefulLife() |
| | | ); |
| | | BigDecimal accumulatedDepreciation = defaultMoney(asset.getAccumulatedDepreciation()).add(monthlyDepreciation); |
| | | if (accumulatedDepreciation.compareTo(defaultMoney(asset.getOriginalValue())) > 0) { |
| | | accumulatedDepreciation = defaultMoney(asset.getOriginalValue()); |
| | | } |
| | | asset.setAccumulatedDepreciation(roundMoney(accumulatedDepreciation)); |
| | | asset.setNetValue(calculateNetValue(asset.getOriginalValue(), asset.getAccumulatedDepreciation())); |
| | | updateById(asset); |
| | | processedCount++; |
| | | totalMonthlyDepreciation = totalMonthlyDepreciation.add(monthlyDepreciation); |
| | | } |
| | | Map<String, Object> result = new HashMap<>(4); |
| | | result.put("processedCount", processedCount); |
| | | result.put("totalMonthlyDepreciation", roundMoney(totalMonthlyDepreciation)); |
| | | result.put("executionTime", LocalDateTime.now()); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * æææ¡£è§åæ ¡éªåºå®èµäº§æ°æ®ã |
| | | */ |
| | | private void validateForSave(FinFixedAssetDto dto, boolean isUpdate) { |
| | | if (dto == null) { |
| | | throw new ServiceException("åºå®èµäº§æ°æ®ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (isUpdate && dto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼èµäº§IDä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getAssetName())) { |
| | | throw new ServiceException("èµäº§åç§°ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getCategory())) { |
| | | throw new ServiceException("èµäº§ç±»å«ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getPurchaseDate() == null) { |
| | | throw new ServiceException("è´ç½®æ¥æä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getOriginalValue() == null || dto.getOriginalValue().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("èµäº§åå¼ä¸è½ä¸ºç©ºä¸ä¸è½å°äº0"); |
| | | } |
| | | if (dto.getUsefulLife() == null || dto.getUsefulLife() <= 0) { |
| | | throw new ServiceException("使ç¨å¹´éå¿
须大äº0"); |
| | | } |
| | | if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("æ®å¼çä¸è½å°äº0"); |
| | | } |
| | | if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(ONE_HUNDRED) > 0) { |
| | | throw new ServiceException("æ®å¼çä¸è½å¤§äº100%"); |
| | | } |
| | | if (StringUtils.isNotEmpty(dto.getAssetCode())) { |
| | | LambdaQueryWrapper<FinFixedAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(FinFixedAsset::getAssetCode, dto.getAssetCode()); |
| | | if (isUpdate) { |
| | | wrapper.ne(FinFixedAsset::getId, dto.getId()); |
| | | } |
| | | if (count(wrapper) > 0) { |
| | | throw new ServiceException("èµäº§ç¼å·å·²åå¨ï¼è¯·å¿éå¤æäº¤"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åºå®èµäº§ææ§å
¬å¼ï¼ |
| | | * monthlyDepreciation = originalValue * (1 - residualRate/100) / (usefulLife*12) |
| | | */ |
| | | private BigDecimal calculateMonthlyDepreciation(BigDecimal originalValue, BigDecimal residualRate, Integer usefulLife) { |
| | | BigDecimal normalizedOriginalValue = defaultMoney(originalValue); |
| | | BigDecimal normalizedResidualRate = normalizeResidualRate(residualRate); |
| | | BigDecimal depreciableRatio = BigDecimal.ONE.subtract(normalizedResidualRate.divide(ONE_HUNDRED, 8, RoundingMode.HALF_UP)); |
| | | BigDecimal months = BigDecimal.valueOf((long) usefulLife * 12L); |
| | | if (months.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new ServiceException("使ç¨å¹´éæ æï¼æ æ³è®¡æææ§"); |
| | | } |
| | | return roundMoney(normalizedOriginalValue.multiply(depreciableRatio).divide(months, 8, RoundingMode.HALF_UP)); |
| | | } |
| | | |
| | | /** |
| | | * åå¼ = åå¼ - ç´¯è®¡ææ§ã |
| | | */ |
| | | private BigDecimal calculateNetValue(BigDecimal originalValue, BigDecimal accumulatedDepreciation) { |
| | | BigDecimal value = defaultMoney(originalValue).subtract(defaultMoney(accumulatedDepreciation)); |
| | | if (value.compareTo(BigDecimal.ZERO) < 0) { |
| | | value = BigDecimal.ZERO; |
| | | } |
| | | return roundMoney(value); |
| | | } |
| | | |
| | | private BigDecimal normalizeResidualRate(BigDecimal residualRate) { |
| | | return residualRate == null ? BigDecimal.ZERO : residualRate; |
| | | } |
| | | |
| | | private BigDecimal defaultMoney(BigDecimal value) { |
| | | return value == null ? ZERO : roundMoney(value); |
| | | } |
| | | |
| | | private BigDecimal roundMoney(BigDecimal value) { |
| | | if (value == null) { |
| | | return ZERO; |
| | | } |
| | | return value.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private String generateAssetCode() { |
| | | return "GD" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.impl.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.bean.dto.financial.FinIntangibleAssetDto; |
| | | import com.ruoyi.account.mapper.financial.FinIntangibleAssetMapper; |
| | | import com.ruoyi.account.pojo.financial.FinIntangibleAsset; |
| | | import com.ruoyi.account.service.financial.FinIntangibleAssetService; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * æ å½¢èµäº§æå¡å®ç°ã |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class FinIntangibleAssetServiceImpl extends ServiceImpl<FinIntangibleAssetMapper, FinIntangibleAsset> implements FinIntangibleAssetService { |
| | | |
| | | private static final BigDecimal ONE_HUNDRED = new BigDecimal("100"); |
| | | private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); |
| | | private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); |
| | | |
| | | @Override |
| | | public IPage<FinIntangibleAsset> pageList(Page<FinIntangibleAsset> page, FinIntangibleAssetDto queryDto) { |
| | | LambdaQueryWrapper<FinIntangibleAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetCode())) { |
| | | wrapper.like(FinIntangibleAsset::getAssetCode, queryDto.getAssetCode()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getAssetName())) { |
| | | wrapper.like(FinIntangibleAsset::getAssetName, queryDto.getAssetName()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getCategory())) { |
| | | wrapper.eq(FinIntangibleAsset::getCategory, queryDto.getCategory()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getStatus())) { |
| | | wrapper.eq(FinIntangibleAsset::getStatus, queryDto.getStatus()); |
| | | } |
| | | wrapper.orderByDesc(FinIntangibleAsset::getId); |
| | | return page(page, wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean add(FinIntangibleAssetDto dto) { |
| | | validateForSave(dto, false); |
| | | if (StringUtils.isEmpty(dto.getAssetCode())) { |
| | | dto.setAssetCode(generateAssetCode()); |
| | | } |
| | | BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate()); |
| | | dto.setResidualRate(residualRate); |
| | | BigDecimal accumulatedAmortization = defaultMoney(dto.getAccumulatedAmortization()); |
| | | dto.setAccumulatedAmortization(accumulatedAmortization); |
| | | dto.setNetValue(calculateNetValue(dto.getOriginalValue(), accumulatedAmortization)); |
| | | if (StringUtils.isEmpty(dto.getStatus())) { |
| | | dto.setStatus("in_use"); |
| | | } |
| | | return save(dto); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean update(FinIntangibleAssetDto dto) { |
| | | if (dto == null || dto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼èµäº§IDä¸è½ä¸ºç©º"); |
| | | } |
| | | FinIntangibleAsset existed = getById(dto.getId()); |
| | | if (existed == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼æ å½¢èµäº§ä¸åå¨"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getAssetCode())) { |
| | | dto.setAssetCode(existed.getAssetCode()); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getStatus())) { |
| | | dto.setStatus(existed.getStatus()); |
| | | } |
| | | validateForSave(dto, true); |
| | | BigDecimal residualRate = normalizeResidualRate(dto.getResidualRate()); |
| | | dto.setResidualRate(residualRate); |
| | | if (dto.getAccumulatedAmortization() == null) { |
| | | dto.setAccumulatedAmortization(defaultMoney(existed.getAccumulatedAmortization())); |
| | | } |
| | | dto.setNetValue(calculateNetValue(dto.getOriginalValue(), dto.getAccumulatedAmortization())); |
| | | if (dto.getNetValue().compareTo(BigDecimal.ZERO) <= 0) { |
| | | dto.setStatus("amortized"); |
| | | } else if ("amortized".equals(dto.getStatus())) { |
| | | dto.setStatus("in_use"); |
| | | } |
| | | if (dto.getValidityDate() != null |
| | | && dto.getValidityDate().isBefore(LocalDate.now()) |
| | | && !"amortized".equals(dto.getStatus())) { |
| | | dto.setStatus("expired"); |
| | | } |
| | | return updateById(dto); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean deleteByIds(List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | throw new ServiceException("å é¤å¤±è´¥ï¼è¯·éæ©è¦å é¤çæ°æ®"); |
| | | } |
| | | return removeByIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Map<String, Object> amortize(List<Long> ids) { |
| | | LambdaQueryWrapper<FinIntangibleAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | if (ids != null && !ids.isEmpty()) { |
| | | wrapper.in(FinIntangibleAsset::getId, ids); |
| | | } else { |
| | | wrapper.eq(FinIntangibleAsset::getStatus, "in_use"); |
| | | } |
| | | List<FinIntangibleAsset> assets = list(wrapper); |
| | | BigDecimal totalMonthlyAmortization = ZERO; |
| | | int processedCount = 0; |
| | | for (FinIntangibleAsset asset : assets) { |
| | | if (!"in_use".equals(asset.getStatus())) { |
| | | continue; |
| | | } |
| | | BigDecimal monthlyAmortization = calculateMonthlyAmortization( |
| | | asset.getOriginalValue(), |
| | | asset.getResidualRate(), |
| | | asset.getAmortizationPeriod() |
| | | ); |
| | | BigDecimal accumulatedAmortization = defaultMoney(asset.getAccumulatedAmortization()).add(monthlyAmortization); |
| | | if (accumulatedAmortization.compareTo(defaultMoney(asset.getOriginalValue())) > 0) { |
| | | accumulatedAmortization = defaultMoney(asset.getOriginalValue()); |
| | | } |
| | | asset.setAccumulatedAmortization(roundMoney(accumulatedAmortization)); |
| | | asset.setNetValue(calculateNetValue(asset.getOriginalValue(), asset.getAccumulatedAmortization())); |
| | | |
| | | // è§åï¼å½åå¼ <= 0 æ¶ï¼åå¼å½é¶å¹¶æ 记为已æéå®ã |
| | | if (asset.getNetValue().compareTo(BigDecimal.ZERO) <= 0) { |
| | | asset.setNetValue(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); |
| | | asset.setStatus("amortized"); |
| | | } else if (asset.getValidityDate() != null && asset.getValidityDate().isBefore(LocalDate.now())) { |
| | | asset.setStatus("expired"); |
| | | } |
| | | updateById(asset); |
| | | processedCount++; |
| | | totalMonthlyAmortization = totalMonthlyAmortization.add(monthlyAmortization); |
| | | } |
| | | Map<String, Object> result = new HashMap<>(4); |
| | | result.put("processedCount", processedCount); |
| | | result.put("totalMonthlyAmortization", roundMoney(totalMonthlyAmortization)); |
| | | result.put("executionTime", LocalDateTime.now()); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * æææ¡£è§åæ ¡éªæ å½¢èµäº§æ°æ®ã |
| | | */ |
| | | private void validateForSave(FinIntangibleAssetDto dto, boolean isUpdate) { |
| | | if (dto == null) { |
| | | throw new ServiceException("æ å½¢èµäº§æ°æ®ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (isUpdate && dto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼èµäº§IDä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getAssetName())) { |
| | | throw new ServiceException("èµäº§åç§°ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getCategory())) { |
| | | throw new ServiceException("èµäº§ç±»å«ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getAcquisitionDate() == null) { |
| | | throw new ServiceException("å徿¥æä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getOriginalValue() == null || dto.getOriginalValue().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("èµäº§åå¼ä¸è½ä¸ºç©ºä¸ä¸è½å°äº0"); |
| | | } |
| | | if (dto.getAmortizationPeriod() == null || dto.getAmortizationPeriod() <= 0) { |
| | | throw new ServiceException("æéå¹´éå¿
须大äº0"); |
| | | } |
| | | if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("æ®å¼çä¸è½å°äº0"); |
| | | } |
| | | if (dto.getResidualRate() != null && dto.getResidualRate().compareTo(ONE_HUNDRED) > 0) { |
| | | throw new ServiceException("æ®å¼çä¸è½å¤§äº100%"); |
| | | } |
| | | if (StringUtils.isNotEmpty(dto.getAssetCode())) { |
| | | LambdaQueryWrapper<FinIntangibleAsset> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(FinIntangibleAsset::getAssetCode, dto.getAssetCode()); |
| | | if (isUpdate) { |
| | | wrapper.ne(FinIntangibleAsset::getId, dto.getId()); |
| | | } |
| | | if (count(wrapper) > 0) { |
| | | throw new ServiceException("èµäº§ç¼å·å·²åå¨ï¼è¯·å¿éå¤æäº¤"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ å½¢èµäº§æéå
¬å¼ï¼ |
| | | * monthlyAmortization = originalValue * (1 - residualRate/100) / (amortizationPeriod*12) |
| | | */ |
| | | private BigDecimal calculateMonthlyAmortization(BigDecimal originalValue, BigDecimal residualRate, Integer amortizationPeriod) { |
| | | BigDecimal normalizedOriginalValue = defaultMoney(originalValue); |
| | | BigDecimal normalizedResidualRate = normalizeResidualRate(residualRate); |
| | | BigDecimal amortizableRatio = BigDecimal.ONE.subtract(normalizedResidualRate.divide(ONE_HUNDRED, 8, RoundingMode.HALF_UP)); |
| | | BigDecimal months = BigDecimal.valueOf((long) amortizationPeriod * 12L); |
| | | if (months.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new ServiceException("æéå¹´éæ æï¼æ æ³è®¡ææé"); |
| | | } |
| | | return roundMoney(normalizedOriginalValue.multiply(amortizableRatio).divide(months, 8, RoundingMode.HALF_UP)); |
| | | } |
| | | |
| | | /** |
| | | * åå¼ = åå¼ - 累计æéã |
| | | */ |
| | | private BigDecimal calculateNetValue(BigDecimal originalValue, BigDecimal accumulatedAmortization) { |
| | | BigDecimal value = defaultMoney(originalValue).subtract(defaultMoney(accumulatedAmortization)); |
| | | if (value.compareTo(BigDecimal.ZERO) < 0) { |
| | | value = BigDecimal.ZERO; |
| | | } |
| | | return roundMoney(value); |
| | | } |
| | | |
| | | private BigDecimal normalizeResidualRate(BigDecimal residualRate) { |
| | | return residualRate == null ? BigDecimal.ZERO : residualRate; |
| | | } |
| | | |
| | | private BigDecimal defaultMoney(BigDecimal value) { |
| | | return value == null ? ZERO : roundMoney(value); |
| | | } |
| | | |
| | | private BigDecimal roundMoney(BigDecimal value) { |
| | | if (value == null) { |
| | | return ZERO; |
| | | } |
| | | return value.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private String generateAssetCode() { |
| | | return "WX" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.impl.financial; |
| | | |
| | | import com.ruoyi.account.bean.dto.financial.FinDetailLedgerQueryDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinLedgerQueryDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinLedgerEntryRecordVo; |
| | | import com.ruoyi.account.bean.vo.financial.FinLedgerRowVo; |
| | | import com.ruoyi.account.mapper.financial.FinVoucherEntryMapper; |
| | | import com.ruoyi.account.service.financial.FinLedgerService; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.YearMonth; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.format.DateTimeParseException; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * ç§ç®æ»è´¦/æç»è´¦æå¡å®ç°ã |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class FinLedgerServiceImpl implements FinLedgerService { |
| | | |
| | | private static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM"); |
| | | private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); |
| | | |
| | | private final FinVoucherEntryMapper finVoucherEntryMapper; |
| | | |
| | | @Override |
| | | public List<FinLedgerRowVo> queryGeneralLedger(FinLedgerQueryDto queryDto) { |
| | | if (queryDto == null || StringUtils.isEmpty(queryDto.getSubjectCode())) { |
| | | return Collections.emptyList(); |
| | | } |
| | | YearMonth startMonth = parseMonth(queryDto.getStartMonth(), "å¼å§æä»½"); |
| | | YearMonth endMonth = parseMonth(queryDto.getEndMonth(), "ç»ææä»½"); |
| | | if (startMonth.isAfter(endMonth)) { |
| | | throw new ServiceException("å¼å§æä»½ä¸è½å¤§äºç»ææä»½"); |
| | | } |
| | | return Collections.singletonList(buildGeneralLedgerTotalRow(queryDto.getSubjectCode(), startMonth, endMonth)); |
| | | } |
| | | |
| | | @Override |
| | | public List<FinLedgerRowVo> queryDetailLedger(FinDetailLedgerQueryDto queryDto) { |
| | | if (queryDto == null || StringUtils.isEmpty(queryDto.getSubjectCode())) { |
| | | return Collections.emptyList(); |
| | | } |
| | | YearMonth startMonth = parseMonth(queryDto.getStartMonth(), "å¼å§æä»½"); |
| | | YearMonth endMonth = parseMonth(queryDto.getEndMonth(), "ç»ææä»½"); |
| | | if (startMonth.isAfter(endMonth)) { |
| | | throw new ServiceException("å¼å§æä»½ä¸è½å¤§äºç»ææä»½"); |
| | | } |
| | | return buildLedgerRows(queryDto.getSubjectCode(), startMonth, endMonth, queryDto.getAuxiliaryType(), queryDto.getAuxiliaryId()); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºè´¦ç°¿è¡æ°æ®ï¼è¾åºæåãåå½ãæ¬æåè®¡ãæ¬å¹´ç´¯è®¡ã |
| | | */ |
| | | private List<FinLedgerRowVo> buildLedgerRows(String subjectCode, |
| | | YearMonth startMonth, |
| | | YearMonth endMonth, |
| | | String auxiliaryType, |
| | | String auxiliaryId) { |
| | | LocalDate startDate = startMonth.atDay(1); |
| | | LocalDate endDate = endMonth.atEndOfMonth(); |
| | | |
| | | List<FinLedgerEntryRecordVo> openingEntries = finVoucherEntryMapper.listPostedEntriesBefore( |
| | | subjectCode, startDate, auxiliaryType, auxiliaryId |
| | | ); |
| | | BigDecimal openingBalance = calculateBalance(openingEntries); |
| | | |
| | | List<FinLedgerEntryRecordVo> currentPeriodEntries = finVoucherEntryMapper.listPostedEntries( |
| | | subjectCode, startDate, endDate, auxiliaryType, auxiliaryId |
| | | ); |
| | | Map<YearMonth, List<FinLedgerEntryRecordVo>> monthEntriesMap = groupEntriesByMonth(currentPeriodEntries); |
| | | |
| | | List<FinLedgerRowVo> rows = new ArrayList<>(); |
| | | BigDecimal runningBalance = openingBalance; |
| | | BigDecimal yearDebit = ZERO; |
| | | BigDecimal yearCredit = ZERO; |
| | | |
| | | for (YearMonth month = startMonth; !month.isAfter(endMonth); month = month.plusMonths(1)) { |
| | | rows.add(buildOpeningRow(month.atDay(1), runningBalance)); |
| | | |
| | | List<FinLedgerEntryRecordVo> monthEntries = monthEntriesMap.getOrDefault(month, Collections.emptyList()); |
| | | BigDecimal monthDebit = ZERO; |
| | | BigDecimal monthCredit = ZERO; |
| | | for (FinLedgerEntryRecordVo entry : monthEntries) { |
| | | BigDecimal debit = money(entry.getDebit()); |
| | | BigDecimal credit = money(entry.getCredit()); |
| | | runningBalance = runningBalance.add(debit).subtract(credit); |
| | | monthDebit = monthDebit.add(debit); |
| | | monthCredit = monthCredit.add(credit); |
| | | |
| | | FinLedgerRowVo row = new FinLedgerRowVo(); |
| | | row.setRowType("entry"); |
| | | row.setDate(entry.getVoucherDate()); |
| | | row.setVoucherNo(entry.getVoucherNo()); |
| | | row.setSummary(StringUtils.isNotEmpty(entry.getSummary()) ? entry.getSummary() : ""); |
| | | row.setDebit(debit); |
| | | row.setCredit(credit); |
| | | row.setBalance(money(runningBalance)); |
| | | row.setDirection(resolveDirection(runningBalance)); |
| | | rows.add(row); |
| | | } |
| | | |
| | | rows.add(buildMonthlyTotalRow(month.atEndOfMonth(), monthDebit, monthCredit, runningBalance)); |
| | | yearDebit = yearDebit.add(monthDebit); |
| | | yearCredit = yearCredit.add(monthCredit); |
| | | } |
| | | |
| | | rows.add(buildYearlyTotalRow(endMonth.atEndOfMonth(), yearDebit, yearCredit, runningBalance)); |
| | | return rows; |
| | | } |
| | | |
| | | private FinLedgerRowVo buildGeneralLedgerTotalRow(String subjectCode, YearMonth startMonth, YearMonth endMonth) { |
| | | LocalDate startDate = startMonth.atDay(1); |
| | | LocalDate endDate = endMonth.atEndOfMonth(); |
| | | |
| | | List<FinLedgerEntryRecordVo> openingEntries = finVoucherEntryMapper.listPostedEntriesBefore( |
| | | subjectCode, startDate, null, null |
| | | ); |
| | | BigDecimal openingBalance = calculateBalance(openingEntries); |
| | | |
| | | List<FinLedgerEntryRecordVo> currentPeriodEntries = finVoucherEntryMapper.listPostedEntries( |
| | | subjectCode, startDate, endDate, null, null |
| | | ); |
| | | |
| | | BigDecimal totalDebit = ZERO; |
| | | BigDecimal totalCredit = ZERO; |
| | | for (FinLedgerEntryRecordVo entry : currentPeriodEntries) { |
| | | totalDebit = totalDebit.add(money(entry.getDebit())); |
| | | totalCredit = totalCredit.add(money(entry.getCredit())); |
| | | } |
| | | |
| | | BigDecimal endingBalance = openingBalance.add(totalDebit).subtract(totalCredit); |
| | | FinLedgerRowVo totalRow = new FinLedgerRowVo(); |
| | | totalRow.setRowType("yearly_total"); |
| | | totalRow.setDate(endDate); |
| | | totalRow.setDebit(money(totalDebit)); |
| | | totalRow.setCredit(money(totalCredit)); |
| | | totalRow.setBalance(money(endingBalance)); |
| | | totalRow.setDirection(resolveDirection(endingBalance)); |
| | | return totalRow; |
| | | } |
| | | |
| | | private Map<YearMonth, List<FinLedgerEntryRecordVo>> groupEntriesByMonth(List<FinLedgerEntryRecordVo> entries) { |
| | | Map<YearMonth, List<FinLedgerEntryRecordVo>> map = new LinkedHashMap<>(); |
| | | for (FinLedgerEntryRecordVo entry : entries) { |
| | | if (entry.getVoucherDate() == null) { |
| | | continue; |
| | | } |
| | | YearMonth month = YearMonth.from(entry.getVoucherDate()); |
| | | map.computeIfAbsent(month, key -> new ArrayList<>()).add(entry); |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | private FinLedgerRowVo buildOpeningRow(LocalDate date, BigDecimal openingBalance) { |
| | | FinLedgerRowVo row = new FinLedgerRowVo(); |
| | | row.setRowType("opening"); |
| | | row.setDate(date); |
| | | row.setVoucherNo("-"); |
| | | row.setSummary("æåä½é¢"); |
| | | row.setDebit(ZERO); |
| | | row.setCredit(ZERO); |
| | | row.setBalance(money(openingBalance)); |
| | | row.setDirection(resolveDirection(openingBalance)); |
| | | return row; |
| | | } |
| | | |
| | | private FinLedgerRowVo buildMonthlyTotalRow(LocalDate date, |
| | | BigDecimal monthDebit, |
| | | BigDecimal monthCredit, |
| | | BigDecimal monthBalance) { |
| | | FinLedgerRowVo row = new FinLedgerRowVo(); |
| | | row.setRowType("monthly_total"); |
| | | row.setDate(date); |
| | | row.setVoucherNo("-"); |
| | | row.setSummary("æ¬æå计"); |
| | | row.setDebit(money(monthDebit)); |
| | | row.setCredit(money(monthCredit)); |
| | | row.setBalance(money(monthBalance)); |
| | | row.setDirection(resolveDirection(monthBalance)); |
| | | return row; |
| | | } |
| | | |
| | | private FinLedgerRowVo buildYearlyTotalRow(LocalDate date, |
| | | BigDecimal yearDebit, |
| | | BigDecimal yearCredit, |
| | | BigDecimal yearBalance) { |
| | | FinLedgerRowVo row = new FinLedgerRowVo(); |
| | | row.setRowType("yearly_total"); |
| | | row.setDate(date); |
| | | row.setVoucherNo("-"); |
| | | row.setSummary("å计"); |
| | | row.setDebit(money(yearDebit)); |
| | | row.setCredit(money(yearCredit)); |
| | | row.setBalance(money(yearBalance)); |
| | | row.setDirection(resolveDirection(yearBalance)); |
| | | return row; |
| | | } |
| | | |
| | | private BigDecimal calculateBalance(List<FinLedgerEntryRecordVo> entries) { |
| | | BigDecimal balance = ZERO; |
| | | for (FinLedgerEntryRecordVo entry : entries) { |
| | | balance = balance.add(money(entry.getDebit())).subtract(money(entry.getCredit())); |
| | | } |
| | | return money(balance); |
| | | } |
| | | |
| | | private String resolveDirection(BigDecimal balance) { |
| | | return money(balance).compareTo(BigDecimal.ZERO) >= 0 ? "å" : "è´·"; |
| | | } |
| | | |
| | | private YearMonth parseMonth(String value, String fieldLabel) { |
| | | if (StringUtils.isEmpty(value)) { |
| | | throw new ServiceException(fieldLabel + "ä¸è½ä¸ºç©ºï¼æ ¼å¼åºä¸ºYYYY-MM"); |
| | | } |
| | | try { |
| | | return YearMonth.parse(value, MONTH_FORMATTER); |
| | | } catch (DateTimeParseException ex) { |
| | | throw new ServiceException(fieldLabel + "æ ¼å¼éè¯¯ï¼æ ¼å¼åºä¸ºYYYY-MM"); |
| | | } |
| | | } |
| | | |
| | | private BigDecimal money(BigDecimal value) { |
| | | if (value == null) { |
| | | return ZERO; |
| | | } |
| | | return value.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.account.service.impl.financial; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherEntryDto; |
| | | import com.ruoyi.account.bean.dto.financial.FinVoucherPageDto; |
| | | import com.ruoyi.account.bean.vo.financial.FinVoucherDetailVo; |
| | | import com.ruoyi.account.mapper.AccountSubjectMapper; |
| | | import com.ruoyi.account.mapper.financial.FinVoucherEntryMapper; |
| | | import com.ruoyi.account.mapper.financial.FinVoucherMapper; |
| | | import com.ruoyi.account.pojo.AccountSubject; |
| | | import com.ruoyi.account.pojo.financial.FinVoucher; |
| | | import com.ruoyi.account.pojo.financial.FinVoucherEntry; |
| | | import com.ruoyi.account.service.financial.FinVoucherService; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * åè¯æå¡å®ç°ã |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class FinVoucherServiceImpl extends ServiceImpl<FinVoucherMapper, FinVoucher> implements FinVoucherService { |
| | | |
| | | private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); |
| | | |
| | | private final FinVoucherEntryMapper finVoucherEntryMapper; |
| | | private final AccountSubjectMapper accountSubjectMapper; |
| | | private final FileUtil fileUtil; |
| | | |
| | | @Override |
| | | public IPage<FinVoucher> pageList(Page<FinVoucher> page, FinVoucherPageDto queryDto) { |
| | | LambdaQueryWrapper<FinVoucher> wrapper = new LambdaQueryWrapper<>(); |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getVoucherNo())) { |
| | | wrapper.like(FinVoucher::getVoucherNo, queryDto.getVoucherNo()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getCreator())) { |
| | | wrapper.eq(FinVoucher::getCreator, queryDto.getCreator()); |
| | | } |
| | | if (queryDto != null && StringUtils.isNotEmpty(queryDto.getStatus())) { |
| | | wrapper.eq(FinVoucher::getStatus, queryDto.getStatus()); |
| | | } |
| | | if (queryDto != null && queryDto.getStartDate() != null) { |
| | | wrapper.ge(FinVoucher::getVoucherDate, queryDto.getStartDate()); |
| | | } |
| | | if (queryDto != null && queryDto.getEndDate() != null) { |
| | | wrapper.le(FinVoucher::getVoucherDate, queryDto.getEndDate()); |
| | | } |
| | | wrapper.orderByDesc(FinVoucher::getVoucherDate).orderByDesc(FinVoucher::getId); |
| | | return page(page, wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addVoucher(FinVoucherDto dto) { |
| | | validateVoucherBasicInfo(dto, false); |
| | | List<FinVoucherEntry> validEntries = buildAndValidateEntries(dto); |
| | | |
| | | FinVoucher voucher = new FinVoucher(); |
| | | BeanUtils.copyProperties(dto, voucher); |
| | | voucher.setStatus("unposted"); |
| | | voucher.setAttachmentCount(voucher.getAttachmentCount() == null ? 0 : voucher.getAttachmentCount()); |
| | | BigDecimal totalDebit = calculateTotalDebit(validEntries); |
| | | BigDecimal totalCredit = calculateTotalCredit(validEntries); |
| | | voucher.setDebit(totalDebit); |
| | | voucher.setCredit(totalCredit); |
| | | if (StringUtils.isEmpty(voucher.getSummary())) { |
| | | voucher.setSummary(findDefaultSummary(validEntries)); |
| | | } |
| | | save(voucher); |
| | | saveEntries(voucher.getId(), validEntries); |
| | | // 5. ä¿åéå®å°è´¦éä»¶ |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_VOUCHER, voucher.getId(), dto.getStorageBlobDTOs()); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean updateVoucher(FinVoucherDto dto) { |
| | | validateVoucherBasicInfo(dto, true); |
| | | FinVoucher existed = getById(dto.getId()); |
| | | if (existed == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼åè¯ä¸åå¨"); |
| | | } |
| | | if (!"unposted".equals(existed.getStatus())) { |
| | | throw new ServiceException("ä»
æªè¿è´¦åè¯å
许修æ¹"); |
| | | } |
| | | List<FinVoucherEntry> validEntries = buildAndValidateEntries(dto); |
| | | |
| | | FinVoucher voucher = new FinVoucher(); |
| | | BeanUtils.copyProperties(dto, voucher); |
| | | voucher.setStatus(existed.getStatus()); |
| | | voucher.setAttachmentCount(voucher.getAttachmentCount() == null ? 0 : voucher.getAttachmentCount()); |
| | | BigDecimal totalDebit = calculateTotalDebit(validEntries); |
| | | BigDecimal totalCredit = calculateTotalCredit(validEntries); |
| | | voucher.setDebit(totalDebit); |
| | | voucher.setCredit(totalCredit); |
| | | if (StringUtils.isEmpty(voucher.getSummary())) { |
| | | voucher.setSummary(findDefaultSummary(validEntries)); |
| | | } |
| | | updateById(voucher); |
| | | |
| | | LambdaQueryWrapper<FinVoucherEntry> deleteWrapper = new LambdaQueryWrapper<>(); |
| | | deleteWrapper.eq(FinVoucherEntry::getVoucherId, voucher.getId()); |
| | | finVoucherEntryMapper.delete(deleteWrapper); |
| | | saveEntries(voucher.getId(), validEntries); |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.FIN_VOUCHER, voucher.getId(), dto.getStorageBlobDTOs()); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean postVoucher(Long id) { |
| | | FinVoucher voucher = getById(id); |
| | | if (voucher == null) { |
| | | throw new ServiceException("è¿è´¦å¤±è´¥ï¼åè¯ä¸åå¨"); |
| | | } |
| | | if (!"unposted".equals(voucher.getStatus())) { |
| | | throw new ServiceException("ä»
æªè¿è´¦åè¯å
许è¿è´¦"); |
| | | } |
| | | voucher.setStatus("posted"); |
| | | return updateById(voucher); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean cancelVoucher(Long id) { |
| | | FinVoucher voucher = getById(id); |
| | | if (voucher == null) { |
| | | throw new ServiceException("ä½åºå¤±è´¥ï¼åè¯ä¸åå¨"); |
| | | } |
| | | if (!"unposted".equals(voucher.getStatus())) { |
| | | throw new ServiceException("ä»
æªè¿è´¦åè¯å
许ä½åº"); |
| | | } |
| | | voucher.setStatus("cancelled"); |
| | | return updateById(voucher); |
| | | } |
| | | |
| | | @Override |
| | | public FinVoucherDetailVo detail(Long id) { |
| | | FinVoucher voucher = getById(id); |
| | | if (voucher == null) { |
| | | throw new ServiceException("æ¥è¯¢å¤±è´¥ï¼åè¯ä¸åå¨"); |
| | | } |
| | | LambdaQueryWrapper<FinVoucherEntry> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(FinVoucherEntry::getVoucherId, id) |
| | | .orderByAsc(FinVoucherEntry::getRowNo) |
| | | .orderByAsc(FinVoucherEntry::getId); |
| | | List<FinVoucherEntry> entries = finVoucherEntryMapper.selectList(wrapper); |
| | | |
| | | FinVoucherDetailVo vo = new FinVoucherDetailVo(); |
| | | BeanUtils.copyProperties(voucher, vo); |
| | | vo.setEntries(entries); |
| | | vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.FIN_VOUCHER, id)); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªåè¯ä¸»è¡¨å段ãç¶æåæ®µä¸å¯ä¸æ§ã |
| | | */ |
| | | private void validateVoucherBasicInfo(FinVoucherDto dto, boolean isUpdate) { |
| | | if (dto == null) { |
| | | throw new ServiceException("åè¯æ°æ®ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (isUpdate && dto.getId() == null) { |
| | | throw new ServiceException("ä¿®æ¹å¤±è´¥ï¼åè¯IDä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getVoucherNo())) { |
| | | throw new ServiceException("åè¯åå·ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (dto.getVoucherDate() == null) { |
| | | throw new ServiceException("åè¯æ¥æä¸è½ä¸ºç©º"); |
| | | } |
| | | LambdaQueryWrapper<FinVoucher> uniqueWrapper = new LambdaQueryWrapper<>(); |
| | | uniqueWrapper.eq(FinVoucher::getVoucherNo, dto.getVoucherNo()); |
| | | if (isUpdate) { |
| | | uniqueWrapper.ne(FinVoucher::getId, dto.getId()); |
| | | } |
| | | if (count(uniqueWrapper) > 0) { |
| | | throw new ServiceException("åè¯åå·å·²åå¨ï¼è¯·å¿éå¤æäº¤"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è¿æ»¤ææåå½å¹¶æ§è¡åè´·å¹³è¡¡æ ¡éªã |
| | | */ |
| | | private List<FinVoucherEntry> buildAndValidateEntries(FinVoucherDto dto) { |
| | | List<FinVoucherEntryDto> rawEntries = dto.getEntries(); |
| | | if (rawEntries == null || rawEntries.isEmpty()) { |
| | | throw new ServiceException("åå½ä¸è½ä¸ºç©ºï¼è³å°éè¦ä¸æ¡ææåå½"); |
| | | } |
| | | List<FinVoucherEntry> validEntries = new ArrayList<>(); |
| | | int rowNo = 1; |
| | | for (FinVoucherEntryDto entryDto : rawEntries) { |
| | | if (entryDto == null || StringUtils.isEmpty(entryDto.getSubjectCode())) { |
| | | continue; |
| | | } |
| | | BigDecimal debit = defaultMoney(entryDto.getDebit()); |
| | | BigDecimal credit = defaultMoney(entryDto.getCredit()); |
| | | if (debit.compareTo(BigDecimal.ZERO) <= 0 && credit.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | if (debit.compareTo(BigDecimal.ZERO) > 0 && credit.compareTo(BigDecimal.ZERO) > 0) { |
| | | throw new ServiceException("åå½åæ¹åè´·æ¹ä¸è½åæ¶å¤§äº0"); |
| | | } |
| | | FinVoucherEntry entry = new FinVoucherEntry(); |
| | | BeanUtils.copyProperties(entryDto, entry); |
| | | entry.setDebit(debit); |
| | | entry.setCredit(credit); |
| | | entry.setRowNo(rowNo++); |
| | | validEntries.add(entry); |
| | | } |
| | | if (validEntries.isEmpty()) { |
| | | throw new ServiceException("åå½è³å°éè¦ä¸æ¡ææè¡ï¼ç§ç®ä¸ç©ºï¼ä¸åæ¹æè´·æ¹å¤§äº0ï¼"); |
| | | } |
| | | |
| | | // åå½ç§ç®å¿
é¡»åå¨ï¼é¿å
èç§ç®ç¼ç å
¥è´¦ã |
| | | Set<String> subjectCodes = validEntries.stream() |
| | | .map(FinVoucherEntry::getSubjectCode) |
| | | .filter(StringUtils::isNotEmpty) |
| | | .collect(Collectors.toSet()); |
| | | if (subjectCodes.isEmpty()) { |
| | | throw new ServiceException("åå½ç§ç®ä¸è½ä¸ºç©º"); |
| | | } |
| | | LambdaQueryWrapper<AccountSubject> subjectWrapper = new LambdaQueryWrapper<>(); |
| | | subjectWrapper.in(AccountSubject::getSubjectCode, subjectCodes); |
| | | List<AccountSubject> subjects = accountSubjectMapper.selectList(subjectWrapper); |
| | | Map<String, AccountSubject> subjectMap = subjects.stream() |
| | | .collect(Collectors.toMap(AccountSubject::getSubjectCode, it -> it, (a, b) -> a)); |
| | | for (FinVoucherEntry entry : validEntries) { |
| | | AccountSubject accountSubject = subjectMap.get(entry.getSubjectCode()); |
| | | if (accountSubject == null) { |
| | | throw new ServiceException("ç§ç®ç¼ç ä¸åå¨ï¼" + entry.getSubjectCode()); |
| | | } |
| | | if (StringUtils.isEmpty(entry.getSubjectName())) { |
| | | entry.setSubjectName(accountSubject.getSubjectName()); |
| | | } |
| | | } |
| | | |
| | | BigDecimal totalDebit = calculateTotalDebit(validEntries); |
| | | BigDecimal totalCredit = calculateTotalCredit(validEntries); |
| | | if (totalDebit.compareTo(BigDecimal.ZERO) <= 0 || totalCredit.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new ServiceException("åè´·éé¢å¿
须大äº0"); |
| | | } |
| | | if (totalDebit.compareTo(totalCredit) != 0) { |
| | | throw new ServiceException("åè´·ä¸å¹³è¡¡ï¼ç¦æ¢ä¿å"); |
| | | } |
| | | return validEntries; |
| | | } |
| | | |
| | | private void saveEntries(Long voucherId, List<FinVoucherEntry> entries) { |
| | | if (voucherId == null) { |
| | | throw new ServiceException("åè¯IDä¸è½ä¸ºç©º"); |
| | | } |
| | | for (FinVoucherEntry entry : entries) { |
| | | entry.setVoucherId(voucherId); |
| | | finVoucherEntryMapper.insert(entry); |
| | | } |
| | | } |
| | | |
| | | private String findDefaultSummary(List<FinVoucherEntry> entries) { |
| | | for (FinVoucherEntry entry : entries) { |
| | | if (StringUtils.isNotEmpty(entry.getSummary())) { |
| | | return entry.getSummary(); |
| | | } |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | private BigDecimal calculateTotalDebit(List<FinVoucherEntry> entries) { |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | for (FinVoucherEntry entry : entries) { |
| | | total = total.add(defaultMoney(entry.getDebit())); |
| | | } |
| | | return total.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private BigDecimal calculateTotalCredit(List<FinVoucherEntry> entries) { |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | for (FinVoucherEntry entry : entries) { |
| | | total = total.add(defaultMoney(entry.getCredit())); |
| | | } |
| | | return total.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private BigDecimal defaultMoney(BigDecimal value) { |
| | | if (value == null) { |
| | | return ZERO; |
| | | } |
| | | return value.setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.ai.assistant; |
| | | |
| | | import dev.langchain4j.service.MemoryId; |
| | | import dev.langchain4j.service.SystemMessage; |
| | | import dev.langchain4j.service.UserMessage; |
| | | import dev.langchain4j.service.spring.AiService; |
| | | import reactor.core.publisher.Flux; |
| | | |
| | | import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT; |
| | | |
| | | @AiService( |
| | | wiringMode = EXPLICIT, |
| | | streamingChatModel = "qwenStreamingChatModel", |
| | | chatMemoryProvider = "chatMemoryProviderManufacturing", |
| | | tools = "manufacturingAgentTools" |
| | | ) |
| | | public interface ManufacturingAgent { |
| | | |
| | | @SystemMessage(fromResource = "manufacturing-agent-prompt.txt") |
| | | Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.ai.assistant; |
| | | |
| | | import com.ruoyi.ai.tools.ManufacturingAgentTools; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | @Component |
| | | public class ManufacturingIntentExecutor { |
| | | |
| | | private static final Pattern LIMIT_PATTERN = Pattern.compile("(å|æè¿)?(\\d{1,2})æ¡"); |
| | | private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})"); |
| | | |
| | | private final ManufacturingAgentTools manufacturingAgentTools; |
| | | |
| | | public ManufacturingIntentExecutor(ManufacturingAgentTools manufacturingAgentTools) { |
| | | this.manufacturingAgentTools = manufacturingAgentTools; |
| | | } |
| | | |
| | | public String tryExecute(String memoryId, String message) { |
| | | if (!StringUtils.hasText(message)) { |
| | | return null; |
| | | } |
| | | String text = message.trim(); |
| | | String keyword = extractKeyword(text); |
| | | Integer limit = extractLimit(text); |
| | | String startDate = extractStartDate(text); |
| | | String endDate = extractEndDate(text); |
| | | |
| | | if (containsAny(text, "é¢è¦", "åè¦", "é£é©", "æé")) { |
| | | return manufacturingAgentTools.getWarningBoard(memoryId, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "åæ", "ç»è®¡", "è¶å¿", "çæ¿", "æ¥è¡¨", "æ»è§")) { |
| | | return manufacturingAgentTools.analyzeFactory(memoryId, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "å", "å¤ç", "派工", "宿", "éç¯", "è·è¿", "å¤ç½®")) { |
| | | return manufacturingAgentTools.planActions(memoryId, text); |
| | | } |
| | | |
| | | if (containsAny(text, "ç产ç°åº", "ç°åº", "车é´")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "site", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "计å", "æäº§", "mps")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "plan", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "å·¥å", "ä½ä¸å", "ä»»å¡å", "ä»»å¡")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "workorder", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "设å¤", "ç»´ä¿®", "ä¿å
»", "æ
é")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "device", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "è´¨é", "è´¨æ£", "ä¸åæ ¼", "æ£éª")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "quality", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "ç©æ", "åºå", "åºä½", "å
¥åº", "åºåº")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "material", keyword, limit, startDate, endDate, text); |
| | | } |
| | | if (containsAny(text, "å¼å¸¸", "ä¾å¤", "åå·®")) { |
| | | return manufacturingAgentTools.queryDomain(memoryId, "exception", keyword, limit, startDate, endDate, text); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private boolean containsAny(String text, String... keywords) { |
| | | for (String keyword : keywords) { |
| | | if (text.toLowerCase().contains(keyword.toLowerCase())) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private Integer extractLimit(String text) { |
| | | Matcher matcher = LIMIT_PATTERN.matcher(text); |
| | | return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10; |
| | | } |
| | | |
| | | private String extractStartDate(String text) { |
| | | Matcher matcher = DATE_PATTERN.matcher(text); |
| | | return matcher.find() ? matcher.group(1) : null; |
| | | } |
| | | |
| | | private String extractEndDate(String text) { |
| | | Matcher matcher = DATE_PATTERN.matcher(text); |
| | | if (!matcher.find()) { |
| | | return null; |
| | | } |
| | | return matcher.find() ? matcher.group(1) : null; |
| | | } |
| | | |
| | | private String extractKeyword(String text) { |
| | | String cleaned = text |
| | | .replace("æ¥è¯¢", "") |
| | | .replace("æ¥ç", "") |
| | | .replace("帮æ", "") |
| | | .replace("请", "") |
| | | .replace("ä¸ä¸", "") |
| | | .replace("ææ", "") |
| | | .replace("å
¨é¨", "") |
| | | .replace("ä»å¹´", "") |
| | | .replace("æ¬å¹´", "") |
| | | .replace("å»å¹´", "") |
| | | .replace("æ¬æ", "") |
| | | .replace("䏿", "") |
| | | .replace("æ¬å¨", "") |
| | | .replace("ä¸å¨", "") |
| | | .replace("ä»å¤©", "") |
| | | .replace("æ¨å¤©", "") |
| | | .replace("è¿30天", "") |
| | | .replace("è¿7天", "") |
| | | .replace("è¿15天", "") |
| | | .replace("è¿60天", "") |
| | | .replace("æè¿30天", "") |
| | | .replace("æè¿7天", "") |
| | | .replace("æè¿15天", "") |
| | | .replace("æè¿60天", "") |
| | | .replace("ç产ç°åº", "") |
| | | .replace("ç°åº", "") |
| | | .replace("ç产工å", "") |
| | | .replace("ç产", "") |
| | | .replace("计å", "") |
| | | .replace("æäº§", "") |
| | | .replace("å·¥å", "") |
| | | .replace("设å¤", "") |
| | | .replace("è´¨é", "") |
| | | .replace("ç©æ", "") |
| | | .replace("åºå", "") |
| | | .replace("å¼å¸¸", "") |
| | | .replace("å10æ¡", "") |
| | | .replace("æè¿10æ¡", "") |
| | | .trim(); |
| | | return cleaned.length() >= 2 ? cleaned : null; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.ai.config; |
| | | |
| | | import com.ruoyi.ai.store.MongoChatMemoryStore; |
| | | import dev.langchain4j.memory.chat.ChatMemoryProvider; |
| | | import dev.langchain4j.memory.chat.MessageWindowChatMemory; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | public class ManufacturingAgentConfig { |
| | | |
| | | @Bean |
| | | ChatMemoryProvider chatMemoryProviderManufacturing(MongoChatMemoryStore mongoChatMemoryStore) { |
| | | return memoryId -> MessageWindowChatMemory.builder() |
| | | .id(memoryId) |
| | | .maxMessages(30) |
| | | .chatMemoryStore(mongoChatMemoryStore) |
| | | .build(); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.ai.controller; |
| | | |
| | | import com.ruoyi.ai.assistant.ManufacturingAgent; |
| | | import com.ruoyi.ai.assistant.ManufacturingIntentExecutor; |
| | | import com.ruoyi.ai.bean.ChatForm; |
| | | import com.ruoyi.ai.context.AiSessionUserContext; |
| | | import com.ruoyi.ai.service.AiChatSessionService; |
| | | import com.ruoyi.ai.store.MongoChatMemoryStore; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import dev.langchain4j.data.message.AiMessage; |
| | | import dev.langchain4j.data.message.UserMessage; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import org.springframework.web.bind.annotation.DeleteMapping; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import reactor.core.publisher.Flux; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Tag(name = "å¶é æºè½å©æ") |
| | | @RestController |
| | | @RequestMapping("/manufacturing-ai") |
| | | public class ManufacturingAiController extends BaseController { |
| | | |
| | | private final ManufacturingAgent manufacturingAgent; |
| | | private final ManufacturingIntentExecutor manufacturingIntentExecutor; |
| | | private final AiSessionUserContext aiSessionUserContext; |
| | | private final MongoChatMemoryStore mongoChatMemoryStore; |
| | | private final AiChatSessionService aiChatSessionService; |
| | | |
| | | public ManufacturingAiController(ManufacturingAgent manufacturingAgent, |
| | | ManufacturingIntentExecutor manufacturingIntentExecutor, |
| | | AiSessionUserContext aiSessionUserContext, |
| | | MongoChatMemoryStore mongoChatMemoryStore, |
| | | AiChatSessionService aiChatSessionService) { |
| | | this.manufacturingAgent = manufacturingAgent; |
| | | this.manufacturingIntentExecutor = manufacturingIntentExecutor; |
| | | this.aiSessionUserContext = aiSessionUserContext; |
| | | this.mongoChatMemoryStore = mongoChatMemoryStore; |
| | | this.aiChatSessionService = aiChatSessionService; |
| | | } |
| | | |
| | | @Operation(summary = "å¶é 对è¯") |
| | | @PostMapping(value = "/chat", produces = "text/stream;charset=utf-8") |
| | | public Flux<String> chat(@RequestBody ChatForm chatForm) { |
| | | if (!StringUtils.hasText(chatForm.getMemoryId())) { |
| | | return Flux.just("memoryIdä¸è½ä¸ºç©º"); |
| | | } |
| | | if (!StringUtils.hasText(chatForm.getMessage())) { |
| | | return Flux.just("messageä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | String memoryId = chatForm.getMemoryId(); |
| | | String userMessage = chatForm.getMessage(); |
| | | |
| | | aiSessionUserContext.bind(memoryId, loginUser); |
| | | aiChatSessionService.touchSession(memoryId, loginUser, userMessage); |
| | | |
| | | String directResponse = manufacturingIntentExecutor.tryExecute(memoryId, userMessage); |
| | | if (StringUtils.isNotEmpty(directResponse)) { |
| | | mongoChatMemoryStore.appendMessages( |
| | | memoryId, |
| | | List.of(UserMessage.from(userMessage), AiMessage.from(directResponse)) |
| | | ); |
| | | aiChatSessionService.refreshSessionStats(memoryId, loginUser); |
| | | return Flux.just(directResponse); |
| | | } |
| | | |
| | | return manufacturingAgent.chat(memoryId, userMessage) |
| | | .doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser)) |
| | | .doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser)); |
| | | } |
| | | |
| | | @Operation(summary = "å¶é ä¼è¯å表") |
| | | @GetMapping("/history/sessions") |
| | | public AjaxResult listSessions() { |
| | | return success(aiChatSessionService.listCurrentUserSessions(SecurityUtils.getLoginUser())); |
| | | } |
| | | |
| | | @Operation(summary = "å¶é ä¼è¯æ¶æ¯") |
| | | @GetMapping("/history/messages/{memoryId}") |
| | | public AjaxResult listMessages(@PathVariable String memoryId) { |
| | | return success(aiChatSessionService.listCurrentUserMessages(memoryId, SecurityUtils.getLoginUser())); |
| | | } |
| | | |
| | | @Operation(summary = "å é¤å¶é ä¼è¯") |
| | | @DeleteMapping("/history/{memoryId}") |
| | | public AjaxResult deleteSession(@PathVariable String memoryId) { |
| | | aiSessionUserContext.remove(memoryId); |
| | | return toAjax(aiChatSessionService.deleteCurrentUserSession(memoryId, SecurityUtils.getLoginUser())); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.ai.tools; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| | | import com.ruoyi.ai.context.AiSessionUserContext; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.device.mapper.DeviceDefectRecordMapper; |
| | | import com.ruoyi.device.mapper.DeviceLedgerMapper; |
| | | import com.ruoyi.device.mapper.DeviceRepairMapper; |
| | | import com.ruoyi.device.pojo.DeviceDefectRecord; |
| | | import com.ruoyi.device.pojo.DeviceLedger; |
| | | import com.ruoyi.device.pojo.DeviceRepair; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementExceptionRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementExceptionRecord; |
| | | import com.ruoyi.production.mapper.ProductionOperationTaskMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionPlanMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionPlan; |
| | | import com.ruoyi.production.pojo.ProductionProductMain; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityUnqualified; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInventory; |
| | | import dev.langchain4j.agent.tool.P; |
| | | import dev.langchain4j.agent.tool.Tool; |
| | | import dev.langchain4j.agent.tool.ToolMemoryId; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Component |
| | | public class ManufacturingAgentTools { |
| | | |
| | | private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | private static final int DEFAULT_LIMIT = 10; |
| | | private static final int MAX_LIMIT = 30; |
| | | private static final int DEVICE_REPAIR_STATUS_PENDING = 0; |
| | | |
| | | private final ProductionPlanMapper productionPlanMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final DeviceLedgerMapper deviceLedgerMapper; |
| | | private final DeviceRepairMapper deviceRepairMapper; |
| | | private final DeviceDefectRecordMapper deviceDefectRecordMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final QualityUnqualifiedMapper qualityUnqualifiedMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | private final ProcurementExceptionRecordMapper procurementExceptionRecordMapper; |
| | | private final AiSessionUserContext aiSessionUserContext; |
| | | |
| | | public ManufacturingAgentTools(ProductionPlanMapper productionPlanMapper, |
| | | ProductionOrderMapper productionOrderMapper, |
| | | ProductionOperationTaskMapper productionOperationTaskMapper, |
| | | ProductionProductMainMapper productionProductMainMapper, |
| | | DeviceLedgerMapper deviceLedgerMapper, |
| | | DeviceRepairMapper deviceRepairMapper, |
| | | DeviceDefectRecordMapper deviceDefectRecordMapper, |
| | | QualityInspectMapper qualityInspectMapper, |
| | | QualityUnqualifiedMapper qualityUnqualifiedMapper, |
| | | StockInventoryMapper stockInventoryMapper, |
| | | ProcurementExceptionRecordMapper procurementExceptionRecordMapper, |
| | | AiSessionUserContext aiSessionUserContext) { |
| | | this.productionPlanMapper = productionPlanMapper; |
| | | this.productionOrderMapper = productionOrderMapper; |
| | | this.productionOperationTaskMapper = productionOperationTaskMapper; |
| | | this.productionProductMainMapper = productionProductMainMapper; |
| | | this.deviceLedgerMapper = deviceLedgerMapper; |
| | | this.deviceRepairMapper = deviceRepairMapper; |
| | | this.deviceDefectRecordMapper = deviceDefectRecordMapper; |
| | | this.qualityInspectMapper = qualityInspectMapper; |
| | | this.qualityUnqualifiedMapper = qualityUnqualifiedMapper; |
| | | this.stockInventoryMapper = stockInventoryMapper; |
| | | this.procurementExceptionRecordMapper = procurementExceptionRecordMapper; |
| | | this.aiSessionUserContext = aiSessionUserContext; |
| | | } |
| | | |
| | | @Tool(name = "æ¥è¯¢å¶é ä¸å¡åæ°æ®", value = "æä¸å¡åæ¥è¯¢ç产ç°åºã计åãå·¥åã设å¤ãè´¨éãç©æãå¼å¸¸å¤çç¸å
³æ°æ®ã") |
| | | public String queryDomain(@ToolMemoryId String memoryId, |
| | | @P(value = "ä¸å¡åï¼site/plan/workorder/device/quality/material/exception") String domain, |
| | | @P(value = "å
³é®åï¼å¯ä¸ä¼ ", required = false) String keyword, |
| | | @P(value = "è¿åæ¡æ°ï¼é»è®¤10ï¼æå¤§30", required = false) Integer limit, |
| | | @P(value = "å¼å§æ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String startDate, |
| | | @P(value = "ç»ææ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String endDate, |
| | | @P(value = "æ¶é´èå´æè¿°ï¼ä¾å¦ä»å¹´ãæ¬æãè¿30天", required = false) String timeRange) { |
| | | LoginUser loginUser = currentLoginUser(memoryId); |
| | | int finalLimit = normalizeLimit(limit); |
| | | DateRange range = resolveDateRange(startDate, endDate, timeRange); |
| | | boolean hasTimeConstraint = hasTimeConstraint(startDate, endDate, timeRange); |
| | | String normalizedDomain = normalizeDomain(domain); |
| | | |
| | | return switch (normalizedDomain) { |
| | | case "site" -> siteSnapshot(loginUser, range); |
| | | case "plan" -> listProductionPlans(loginUser, keyword, finalLimit, range); |
| | | case "workorder" -> listWorkOrders(loginUser, keyword, finalLimit, range); |
| | | case "device" -> isRepairIntent(keyword, timeRange) |
| | | ? listDeviceRepairs(loginUser, normalizeDeviceQueryKeyword(keyword, timeRange), finalLimit, range, hasTimeConstraint) |
| | | : listDevices(loginUser, normalizeDeviceQueryKeyword(keyword, timeRange), finalLimit); |
| | | case "repair" -> listDeviceRepairs(loginUser, normalizeDeviceQueryKeyword(keyword, timeRange), finalLimit, range, hasTimeConstraint); |
| | | case "quality" -> listQualityIssues(loginUser, keyword, finalLimit, range); |
| | | case "material" -> listMaterialInventory(loginUser, keyword, finalLimit); |
| | | case "exception" -> listExceptions(loginUser, keyword, finalLimit, range); |
| | | default -> jsonResponse(false, "manufacturing_query", "䏿¯æçä¸å¡å: " + safe(domain), Map.of(), Map.of(), Map.of()); |
| | | }; |
| | | } |
| | | |
| | | @Tool(name = "å¶é é¢è¦çæ¿", value = "计ç®è®¡åãå·¥åã设å¤ãè´¨éãç©æãå¼å¸¸å¤ççé¢è¦ä¿¡æ¯ã") |
| | | public String getWarningBoard(@ToolMemoryId String memoryId, |
| | | @P(value = "å¼å§æ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String startDate, |
| | | @P(value = "ç»ææ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String endDate, |
| | | @P(value = "æ¶é´èå´æè¿°ï¼ä¾å¦ä»å¤©ãæ¬å¨ãæ¬æãè¿30天", required = false) String timeRange) { |
| | | LoginUser loginUser = currentLoginUser(memoryId); |
| | | DateRange range = resolveDateRange(startDate, endDate, timeRange); |
| | | LocalDate today = LocalDate.now(); |
| | | |
| | | long overduePlanCount = countOverduePlans(loginUser, today); |
| | | long overdueWorkOrderCount = countOverdueWorkOrders(loginUser, today); |
| | | long pendingRepairCount = countPendingRepairs(loginUser); |
| | | long qualityOpenCount = countOpenQualityIssues(loginUser, range); |
| | | long lowStockCount = countLowStock(loginUser); |
| | | long exceptionCount = countExceptionRecords(loginUser, range); |
| | | |
| | | List<Map<String, Object>> warningItems = new ArrayList<>(); |
| | | if (overduePlanCount > 0) { |
| | | warningItems.add(warningItem("high", "计å龿", overduePlanCount, "æç产计åè¶
è¿éæ±æ¥æä»æªå®æ")); |
| | | } |
| | | if (overdueWorkOrderCount > 0) { |
| | | warningItems.add(warningItem("high", "å·¥å龿", overdueWorkOrderCount, "æå·¥å计åç»ææ¥æå·²è¿ä»æªå®å·¥")); |
| | | } |
| | | if (pendingRepairCount > 0) { |
| | | warningItems.add(warningItem("medium", "设å¤å¾
ç»´ä¿®", pendingRepairCount, "åå¨å¾
ç»´ä¿®/ç»´ä¿®ä¸ç设å¤")); |
| | | } |
| | | if (qualityOpenCount > 0) { |
| | | warningItems.add(warningItem("high", "è´¨éæªéç¯", qualityOpenCount, "å卿ªå¤ç宿çä¸åæ ¼è®°å½")); |
| | | } |
| | | if (lowStockCount > 0) { |
| | | warningItems.add(warningItem("medium", "ç©æä½åºå", lowStockCount, "åºåæ°éä½äºæçäºé¢è¦éå¼")); |
| | | } |
| | | if (exceptionCount > 0) { |
| | | warningItems.add(warningItem("medium", "å¼å¸¸è®°å½", exceptionCount, "æ¶é´èå´å
åå¨å¼å¸¸å¤çè®°å½")); |
| | | } |
| | | |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("timeRange", range.label()); |
| | | summary.put("startDate", range.start().toString()); |
| | | summary.put("endDate", range.end().toString()); |
| | | summary.put("warningCount", warningItems.size()); |
| | | summary.put("overduePlanCount", overduePlanCount); |
| | | summary.put("overdueWorkOrderCount", overdueWorkOrderCount); |
| | | summary.put("pendingRepairCount", pendingRepairCount); |
| | | summary.put("qualityOpenCount", qualityOpenCount); |
| | | summary.put("lowStockCount", lowStockCount); |
| | | summary.put("exceptionCount", exceptionCount); |
| | | |
| | | return jsonResponse(true, "manufacturing_warning", "å·²è¿åå¶é é¢è¦çæ¿ã", summary, |
| | | Map.of("items", warningItems), Map.of()); |
| | | } |
| | | |
| | | @Tool(name = "å¶é ç»è¥åæ", value = "ææ¶é´èå´è¾åºå¶é å
³é®ææ ï¼æ¯ææ¥ãé®ãåæåºæ¯ã") |
| | | public String analyzeFactory(@ToolMemoryId String memoryId, |
| | | @P(value = "å¼å§æ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String startDate, |
| | | @P(value = "ç»ææ¥æ yyyy-MM-ddï¼å¯ä¸ä¼ ", required = false) String endDate, |
| | | @P(value = "æ¶é´èå´æè¿°ï¼ä¾å¦æ¬æãè¿30天", required = false) String timeRange) { |
| | | LoginUser loginUser = currentLoginUser(memoryId); |
| | | DateRange range = resolveDateRange(startDate, endDate, timeRange); |
| | | |
| | | long planTotal = countPlans(loginUser, range); |
| | | long planCompleted = countPlansByStatus(loginUser, range, 2); |
| | | long workOrderTotal = countWorkOrders(loginUser, range); |
| | | long workOrderCompleted = countWorkOrdersByStatus(loginUser, range, 2); |
| | | long workOrderInProgress = countWorkOrdersByStatus(loginUser, range, 1); |
| | | |
| | | long outputCount = countOutputs(loginUser, range); |
| | | long deviceTotal = countDevices(loginUser); |
| | | long pendingRepairCount = countPendingRepairs(loginUser); |
| | | long qualityInspectTotal = countQualityInspect(loginUser, range); |
| | | long qualityNgCount = countOpenQualityIssues(loginUser, range); |
| | | long materialSkuCount = countInventorySku(loginUser); |
| | | long lowStockCount = countLowStock(loginUser); |
| | | long exceptionCount = countExceptionRecords(loginUser, range); |
| | | |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("timeRange", range.label()); |
| | | summary.put("startDate", range.start().toString()); |
| | | summary.put("endDate", range.end().toString()); |
| | | summary.put("planTotal", planTotal); |
| | | summary.put("planCompleted", planCompleted); |
| | | summary.put("planCompletionRate", toRate(planCompleted, planTotal)); |
| | | summary.put("workOrderTotal", workOrderTotal); |
| | | summary.put("workOrderCompleted", workOrderCompleted); |
| | | summary.put("workOrderInProgress", workOrderInProgress); |
| | | summary.put("workOrderCompletionRate", toRate(workOrderCompleted, workOrderTotal)); |
| | | summary.put("outputCount", outputCount); |
| | | summary.put("deviceTotal", deviceTotal); |
| | | summary.put("pendingRepairCount", pendingRepairCount); |
| | | summary.put("qualityInspectTotal", qualityInspectTotal); |
| | | summary.put("qualityNgCount", qualityNgCount); |
| | | summary.put("qualityIssueRate", toRate(qualityNgCount, qualityInspectTotal)); |
| | | summary.put("materialSkuCount", materialSkuCount); |
| | | summary.put("lowStockCount", lowStockCount); |
| | | summary.put("exceptionCount", exceptionCount); |
| | | |
| | | List<Map<String, Object>> coreMetrics = List.of( |
| | | metric("计å宿ç", toRate(planCompleted, planTotal)), |
| | | metric("å·¥å宿ç", toRate(workOrderCompleted, workOrderTotal)), |
| | | metric("è´¨éå¼å¸¸ç", toRate(qualityNgCount, qualityInspectTotal)), |
| | | metric("ä½åºåå æ¯", toRate(lowStockCount, materialSkuCount)) |
| | | ); |
| | | |
| | | Map<String, Object> charts = new LinkedHashMap<>(); |
| | | charts.put("domainBarOption", buildDomainBarOption(summary)); |
| | | charts.put("qualityPieOption", buildQualityPieOption(qualityInspectTotal, qualityNgCount)); |
| | | |
| | | return jsonResponse(true, "manufacturing_analysis", "å·²è¿åå¶é åæç»æã", summary, |
| | | Map.of("coreMetrics", coreMetrics), charts); |
| | | } |
| | | |
| | | @Tool(name = "çæå¶é åç建议", value = "æ ¹æ®ç¨æ·é®é¢è¾åºå¯æ§è¡çåçå¨ä½å»ºè®®ï¼å
æ¬ç®æ ä¸å¡æ¥å£ãå¿
å¡«åæ®µå示ä¾ã") |
| | | public String planActions(@ToolMemoryId String memoryId, |
| | | @P("ç¨æ·è¯æ±åæ") String userQuery) { |
| | | LoginUser loginUser = currentLoginUser(memoryId); |
| | | List<Map<String, Object>> actionCards = new ArrayList<>(); |
| | | |
| | | if (!StringUtils.hasText(userQuery) || containsAny(userQuery, "å·¥å", "派工", "ä½ä¸")) { |
| | | actionCards.add(actionCard( |
| | | "workorder_assign", |
| | | "工忴¾å·¥", |
| | | "POST", |
| | | "/productionOperationTask/assign", |
| | | List.of("id", "userIds"), |
| | | Map.of("id", 10001, "userIds", "12,13"), |
| | | "å°å·¥ååé
ç»æå®äººåï¼éç¨äºç°åºè°åº¦ã")); |
| | | } |
| | | if (!StringUtils.hasText(userQuery) || containsAny(userQuery, "设å¤", "ç»´ä¿®", "æ
é")) { |
| | | actionCards.add(actionCard( |
| | | "device_repair_create", |
| | | "å建设å¤ç»´ä¿®å", |
| | | "POST", |
| | | "/device/repair", |
| | | List.of("deviceLedgerId", "deviceName", "repairName", "remark"), |
| | | Map.of("deviceLedgerId", 1001, "deviceName", "ç©ºåæºA-01", "repairName", "å¼ ä¸", "remark", "å¼å并伴鿏©å"), |
| | | "æ°å»ºç»´ä¿®åï¼è¿å
¥è®¾å¤å¼å¸¸å¤çéç¯ã")); |
| | | } |
| | | if (!StringUtils.hasText(userQuery) || containsAny(userQuery, "è´¨é", "ä¸åæ ¼", "éç¯")) { |
| | | actionCards.add(actionCard( |
| | | "quality_unqualified_deal", |
| | | "å¤çä¸åæ ¼å", |
| | | "POST", |
| | | "/quality/qualityUnqualified/deal", |
| | | List.of("id", "dealResult", "dealName"), |
| | | Map.of("id", 3001, "dealResult", "è¿å·¥å夿£", "dealName", "æå"), |
| | | "对ä¸åæ ¼è®°å½æ§è¡å¤ç½®å¹¶éç¯ã")); |
| | | } |
| | | if (!StringUtils.hasText(userQuery) || containsAny(userQuery, "ç©æ", "åºå", "è¡¥æ")) { |
| | | actionCards.add(actionCard( |
| | | "material_inbound", |
| | | "è¡¥å
åºå", |
| | | "POST", |
| | | "/stockInventory/addstockInventory", |
| | | List.of("productModelId", "batchNo", "qualitity"), |
| | | Map.of("productModelId", 5001, "batchNo", "B2026051601", "qualitity", 120), |
| | | "å½ä½åºåé¢è¦è§¦åæ¶ï¼å¢å åºåæ°éã")); |
| | | } |
| | | if (!StringUtils.hasText(userQuery) || containsAny(userQuery, "å¼å¸¸", "éè´å¼å¸¸", "æ¥æå¼å¸¸")) { |
| | | actionCards.add(actionCard( |
| | | "procurement_exception_add", |
| | | "ç»è®°å¼å¸¸è®°å½", |
| | | "POST", |
| | | "/procurementExceptionRecord/add", |
| | | List.of("purchaseLedgerId", "exceptionReason", "exceptionNum"), |
| | | Map.of("purchaseLedgerId", 888, "exceptionReason", "å°æç缺", "exceptionNum", 24), |
| | | "ç»è®°éè´/æ¥æå¼å¸¸ï¼ä¾¿äºåç»è¿½è¸ªååæã")); |
| | | } |
| | | |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("actionCount", actionCards.size()); |
| | | summary.put("userId", loginUser.getUserId()); |
| | | summary.put("tenantId", loginUser.getTenantId()); |
| | | |
| | | return jsonResponse(true, "manufacturing_action_plan", "å·²çæåç建议ï¼è¯·å端å¼å¯¼ç¨æ·ç¡®è®¤åè°ç¨ç®æ ä¸å¡æ¥å£ã", |
| | | summary, Map.of("actionCards", actionCards), Map.of()); |
| | | } |
| | | |
| | | private String siteSnapshot(LoginUser loginUser, DateRange range) { |
| | | long planTotal = countPlans(loginUser, range); |
| | | long workOrderTotal = countWorkOrders(loginUser, range); |
| | | long outputCount = countOutputs(loginUser, range); |
| | | long deviceTotal = countDevices(loginUser); |
| | | long pendingRepairCount = countPendingRepairs(loginUser); |
| | | long qualityOpenCount = countOpenQualityIssues(loginUser, range); |
| | | long lowStockCount = countLowStock(loginUser); |
| | | long exceptionCount = countExceptionRecords(loginUser, range); |
| | | |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("timeRange", range.label()); |
| | | summary.put("startDate", range.start().toString()); |
| | | summary.put("endDate", range.end().toString()); |
| | | summary.put("planTotal", planTotal); |
| | | summary.put("workOrderTotal", workOrderTotal); |
| | | summary.put("outputCount", outputCount); |
| | | summary.put("deviceTotal", deviceTotal); |
| | | summary.put("pendingRepairCount", pendingRepairCount); |
| | | summary.put("qualityOpenCount", qualityOpenCount); |
| | | summary.put("lowStockCount", lowStockCount); |
| | | summary.put("exceptionCount", exceptionCount); |
| | | |
| | | return jsonResponse(true, "manufacturing_site_snapshot", "å·²è¿åç产ç°åºæ¦è§ã", summary, Map.of(), Map.of()); |
| | | } |
| | | |
| | | private String listProductionPlans(LoginUser loginUser, String keyword, int limit, DateRange range) { |
| | | LambdaQueryWrapper<ProductionPlan> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionPlan::getDeptId); |
| | | wrapper.ge(ProductionPlan::getRequiredDate, range.start()).le(ProductionPlan::getRequiredDate, range.end()); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.and(w -> w.like(ProductionPlan::getMpsNo, keyword) |
| | | .or().like(ProductionPlan::getRemark, keyword) |
| | | .or().like(ProductionPlan::getSource, keyword)); |
| | | } |
| | | wrapper.orderByDesc(ProductionPlan::getRequiredDate, ProductionPlan::getId).last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(productionPlanMapper.selectList(wrapper)).stream() |
| | | .map(this::toPlanItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_plan_list", "å·²è¿åç产计åå表ã", |
| | | rangeSummary(range, items.size(), keyword), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listWorkOrders(LoginUser loginUser, String keyword, int limit, DateRange range) { |
| | | LambdaQueryWrapper<ProductionOperationTask> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionOperationTask::getDeptId); |
| | | wrapper.ge(ProductionOperationTask::getPlanStartTime, range.start()) |
| | | .le(ProductionOperationTask::getPlanEndTime, range.end()); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.and(w -> w.like(ProductionOperationTask::getWorkOrderNo, keyword) |
| | | .or().like(ProductionOperationTask::getUserIds, keyword)); |
| | | } |
| | | wrapper.orderByDesc(ProductionOperationTask::getPlanEndTime, ProductionOperationTask::getId) |
| | | .last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(productionOperationTaskMapper.selectList(wrapper)).stream() |
| | | .map(this::toWorkOrderItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_workorder_list", "å·²è¿åå·¥åå表ã", |
| | | rangeSummary(range, items.size(), keyword), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listDevices(LoginUser loginUser, String keyword, int limit) { |
| | | LambdaQueryWrapper<DeviceLedger> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceLedger::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceLedger::getDeptId); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.and(w -> w.like(DeviceLedger::getDeviceName, keyword) |
| | | .or().like(DeviceLedger::getDeviceModel, keyword) |
| | | .or().like(DeviceLedger::getDeviceBrand, keyword)); |
| | | } |
| | | wrapper.orderByDesc(DeviceLedger::getId).last("limit " + limit); |
| | | |
| | | Map<Long, Long> pendingRepairMap = pendingRepairCountByDevice(loginUser); |
| | | List<Map<String, Object>> items = defaultList(deviceLedgerMapper.selectList(wrapper)).stream() |
| | | .map(item -> toDeviceItem(item, pendingRepairMap.getOrDefault(item.getId(), 0L))) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_device_list", "å·²è¿å设å¤å表ã", |
| | | Map.of("count", items.size(), "keyword", safe(keyword)), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listDeviceRepairs(LoginUser loginUser, String keyword, int limit, DateRange range, boolean hasTimeConstraint) { |
| | | LambdaQueryWrapper<DeviceRepair> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceRepair::getTenantId); |
| | | Long currentDeptId = loginUser.getCurrentDeptId(); |
| | | if (currentDeptId != null) { |
| | | wrapper.and(w -> w.eq(DeviceRepair::getDeptId, currentDeptId).or().isNull(DeviceRepair::getDeptId)); |
| | | } |
| | | if (hasTimeConstraint) { |
| | | wrapper.ge(DeviceRepair::getCreateTime, range.start().atStartOfDay()) |
| | | .lt(DeviceRepair::getCreateTime, range.end().plusDays(1).atStartOfDay()); |
| | | } |
| | | if (StringUtils.hasText(keyword)) { |
| | | List<Long> matchedDeviceIds = findDeviceLedgerIdsByKeyword(loginUser, keyword); |
| | | wrapper.and(w -> { |
| | | w.like(DeviceRepair::getDeviceName, keyword) |
| | | .or().like(DeviceRepair::getDeviceModel, keyword) |
| | | .or().like(DeviceRepair::getRemark, keyword) |
| | | .or().like(DeviceRepair::getRepairName, keyword) |
| | | .or().like(DeviceRepair::getMaintenanceName, keyword); |
| | | if (!matchedDeviceIds.isEmpty()) { |
| | | w.or().in(DeviceRepair::getDeviceLedgerId, matchedDeviceIds); |
| | | } |
| | | }); |
| | | } |
| | | wrapper.orderByDesc(DeviceRepair::getCreateTime, DeviceRepair::getId).last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(deviceRepairMapper.selectList(wrapper)).stream() |
| | | .map(this::toDeviceRepairItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_device_repair_list", "å·²è¿å设å¤ç»´ä¿®è®°å½ã", |
| | | rangeSummary(range, items.size(), keyword), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listQualityIssues(LoginUser loginUser, String keyword, int limit, DateRange range) { |
| | | LambdaQueryWrapper<QualityUnqualified> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), QualityUnqualified::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), QualityUnqualified::getDeptId); |
| | | wrapper.ge(QualityUnqualified::getCheckTime, toDate(range.start())) |
| | | .lt(QualityUnqualified::getCheckTime, toExclusiveEndDate(range.end())); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.and(w -> w.like(QualityUnqualified::getProductName, keyword) |
| | | .or().like(QualityUnqualified::getDefectivePhenomena, keyword) |
| | | .or().like(QualityUnqualified::getDealResult, keyword)); |
| | | } |
| | | wrapper.orderByDesc(QualityUnqualified::getCheckTime, QualityUnqualified::getId).last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(qualityUnqualifiedMapper.selectList(wrapper)).stream() |
| | | .map(this::toQualityItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_quality_list", "å·²è¿åè´¨éå¼å¸¸å表ã", |
| | | rangeSummary(range, items.size(), keyword), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listMaterialInventory(LoginUser loginUser, String keyword, int limit) { |
| | | LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), StockInventory::getDeptId); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.and(w -> w.like(StockInventory::getBatchNo, keyword) |
| | | .or().like(StockInventory::getProductModelId, keyword)); |
| | | } |
| | | wrapper.orderByDesc(StockInventory::getId).last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(stockInventoryMapper.selectList(wrapper)).stream() |
| | | .map(this::toMaterialItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_material_list", "å·²è¿åç©æåºåå表ã", |
| | | Map.of("count", items.size(), "keyword", safe(keyword)), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private String listExceptions(LoginUser loginUser, String keyword, int limit, DateRange range) { |
| | | LambdaQueryWrapper<ProcurementExceptionRecord> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), ProcurementExceptionRecord::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProcurementExceptionRecord::getDeptId); |
| | | wrapper.ge(ProcurementExceptionRecord::getCreateTime, range.start().atStartOfDay()) |
| | | .lt(ProcurementExceptionRecord::getCreateTime, range.end().plusDays(1).atStartOfDay()); |
| | | if (StringUtils.hasText(keyword)) { |
| | | wrapper.like(ProcurementExceptionRecord::getExceptionReason, keyword); |
| | | } |
| | | wrapper.orderByDesc(ProcurementExceptionRecord::getCreateTime, ProcurementExceptionRecord::getId) |
| | | .last("limit " + limit); |
| | | |
| | | List<Map<String, Object>> items = defaultList(procurementExceptionRecordMapper.selectList(wrapper)).stream() |
| | | .map(this::toExceptionItem) |
| | | .collect(Collectors.toList()); |
| | | return jsonResponse(true, "manufacturing_exception_list", "å·²è¿åå¼å¸¸å¤çå表ã", |
| | | rangeSummary(range, items.size(), keyword), Map.of("items", items), Map.of()); |
| | | } |
| | | |
| | | private long countPlans(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<ProductionPlan> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionPlan::getDeptId); |
| | | wrapper.ge(ProductionPlan::getRequiredDate, range.start()).le(ProductionPlan::getRequiredDate, range.end()); |
| | | return productionPlanMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countPlansByStatus(LoginUser loginUser, DateRange range, int status) { |
| | | LambdaQueryWrapper<ProductionPlan> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionPlan::getDeptId); |
| | | wrapper.ge(ProductionPlan::getRequiredDate, range.start()) |
| | | .le(ProductionPlan::getRequiredDate, range.end()) |
| | | .eq(ProductionPlan::getStatus, status); |
| | | return productionPlanMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countWorkOrders(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<ProductionOperationTask> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionOperationTask::getDeptId); |
| | | wrapper.ge(ProductionOperationTask::getPlanStartTime, range.start()) |
| | | .le(ProductionOperationTask::getPlanEndTime, range.end()); |
| | | return productionOperationTaskMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countWorkOrdersByStatus(LoginUser loginUser, DateRange range, int status) { |
| | | LambdaQueryWrapper<ProductionOperationTask> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionOperationTask::getDeptId); |
| | | wrapper.ge(ProductionOperationTask::getPlanStartTime, range.start()) |
| | | .le(ProductionOperationTask::getPlanEndTime, range.end()) |
| | | .eq(ProductionOperationTask::getStatus, status); |
| | | return productionOperationTaskMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countOutputs(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<ProductionProductMain> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionProductMain::getDeptId); |
| | | wrapper.ge(ProductionProductMain::getCreateTime, range.start().atStartOfDay()) |
| | | .lt(ProductionProductMain::getCreateTime, range.end().plusDays(1).atStartOfDay()); |
| | | return productionProductMainMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countDevices(LoginUser loginUser) { |
| | | LambdaQueryWrapper<DeviceLedger> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceLedger::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceLedger::getDeptId); |
| | | return deviceLedgerMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countPendingRepairs(LoginUser loginUser) { |
| | | LambdaQueryWrapper<DeviceRepair> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceRepair::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceRepair::getDeptId); |
| | | wrapper.eq(DeviceRepair::getStatus, DEVICE_REPAIR_STATUS_PENDING); |
| | | return deviceRepairMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countQualityInspect(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<QualityInspect> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), QualityInspect::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), QualityInspect::getDeptId); |
| | | wrapper.ge(QualityInspect::getCheckTime, toDate(range.start())) |
| | | .lt(QualityInspect::getCheckTime, toExclusiveEndDate(range.end())); |
| | | return qualityInspectMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countOpenQualityIssues(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<QualityUnqualified> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), QualityUnqualified::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), QualityUnqualified::getDeptId); |
| | | wrapper.ge(QualityUnqualified::getCheckTime, toDate(range.start())) |
| | | .lt(QualityUnqualified::getCheckTime, toExclusiveEndDate(range.end())) |
| | | .ne(QualityUnqualified::getInspectState, 2); |
| | | return qualityUnqualifiedMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countInventorySku(LoginUser loginUser) { |
| | | LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), StockInventory::getDeptId); |
| | | return stockInventoryMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countLowStock(LoginUser loginUser) { |
| | | LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), StockInventory::getDeptId); |
| | | wrapper.isNotNull(StockInventory::getWarnNum); |
| | | List<StockInventory> stocks = defaultList(stockInventoryMapper.selectList(wrapper)); |
| | | return stocks.stream() |
| | | .filter(this::isLowStock) |
| | | .count(); |
| | | } |
| | | |
| | | private long countExceptionRecords(LoginUser loginUser, DateRange range) { |
| | | LambdaQueryWrapper<ProcurementExceptionRecord> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), ProcurementExceptionRecord::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProcurementExceptionRecord::getDeptId); |
| | | wrapper.ge(ProcurementExceptionRecord::getCreateTime, range.start().atStartOfDay()) |
| | | .lt(ProcurementExceptionRecord::getCreateTime, range.end().plusDays(1).atStartOfDay()); |
| | | return procurementExceptionRecordMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countOverduePlans(LoginUser loginUser, LocalDate today) { |
| | | LambdaQueryWrapper<ProductionPlan> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionPlan::getDeptId); |
| | | wrapper.lt(ProductionPlan::getRequiredDate, today).ne(ProductionPlan::getStatus, 2); |
| | | return productionPlanMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private long countOverdueWorkOrders(LoginUser loginUser, LocalDate today) { |
| | | LambdaQueryWrapper<ProductionOperationTask> wrapper = new LambdaQueryWrapper<>(); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), ProductionOperationTask::getDeptId); |
| | | wrapper.lt(ProductionOperationTask::getPlanEndTime, today).ne(ProductionOperationTask::getStatus, 2); |
| | | return productionOperationTaskMapper.selectCount(wrapper); |
| | | } |
| | | |
| | | private Map<Long, Long> pendingRepairCountByDevice(LoginUser loginUser) { |
| | | LambdaQueryWrapper<DeviceRepair> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceRepair::getTenantId); |
| | | applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), DeviceRepair::getDeptId); |
| | | wrapper.eq(DeviceRepair::getStatus, DEVICE_REPAIR_STATUS_PENDING); |
| | | return defaultList(deviceRepairMapper.selectList(wrapper)).stream() |
| | | .filter(item -> item.getDeviceLedgerId() != null) |
| | | .collect(Collectors.groupingBy(DeviceRepair::getDeviceLedgerId, Collectors.counting())); |
| | | } |
| | | |
| | | private Map<String, Object> toPlanItem(ProductionPlan item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("mpsNo", safe(item.getMpsNo())); |
| | | map.put("requiredDate", formatDate(item.getRequiredDate())); |
| | | map.put("promisedDeliveryDate", formatDate(item.getPromisedDeliveryDate())); |
| | | map.put("qtyRequired", item.getQtyRequired()); |
| | | map.put("quantityIssued", item.getQuantityIssued()); |
| | | map.put("status", item.getStatus()); |
| | | map.put("source", safe(item.getSource())); |
| | | map.put("remark", safe(item.getRemark())); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toWorkOrderItem(ProductionOperationTask item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("workOrderNo", safe(item.getWorkOrderNo())); |
| | | map.put("productionOrderId", item.getProductionOrderId()); |
| | | map.put("planStartTime", formatDate(item.getPlanStartTime())); |
| | | map.put("planEndTime", formatDate(item.getPlanEndTime())); |
| | | map.put("actualStartTime", formatDate(item.getActualStartTime())); |
| | | map.put("actualEndTime", formatDate(item.getActualEndTime())); |
| | | map.put("planQuantity", item.getPlanQuantity()); |
| | | map.put("completeQuantity", item.getCompleteQuantity()); |
| | | map.put("status", item.getStatus()); |
| | | map.put("userIds", safe(item.getUserIds())); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toDeviceItem(DeviceLedger item, long pendingRepairCount) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("deviceName", safe(item.getDeviceName())); |
| | | map.put("deviceModel", safe(item.getDeviceModel())); |
| | | map.put("deviceBrand", safe(item.getDeviceBrand())); |
| | | map.put("status", safe(item.getStatus())); |
| | | map.put("storageLocation", safe(item.getStorageLocation())); |
| | | map.put("supplierName", safe(item.getSupplierName())); |
| | | map.put("pendingRepairCount", pendingRepairCount); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toDeviceRepairItem(DeviceRepair item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("deviceLedgerId", item.getDeviceLedgerId()); |
| | | map.put("deviceName", safe(item.getDeviceName())); |
| | | map.put("deviceModel", safe(item.getDeviceModel())); |
| | | map.put("repairTime", formatDate(item.getRepairTime())); |
| | | map.put("repairName", safe(item.getRepairName())); |
| | | map.put("maintenanceName", safe(item.getMaintenanceName())); |
| | | map.put("maintenanceTime", formatDateTime(item.getMaintenanceTime())); |
| | | map.put("maintenanceResult", safe(item.getMaintenanceResult())); |
| | | map.put("acceptanceName", safe(item.getAcceptanceName())); |
| | | map.put("acceptanceTime", formatDateTime(item.getAcceptanceTime())); |
| | | map.put("status", item.getStatus()); |
| | | map.put("remark", safe(item.getRemark())); |
| | | map.put("createTime", formatDateTime(item.getCreateTime())); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toQualityItem(QualityUnqualified item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("checkTime", formatDate(item.getCheckTime())); |
| | | map.put("inspectState", item.getInspectState()); |
| | | map.put("productId", item.getProductId()); |
| | | map.put("productName", safe(item.getProductName())); |
| | | map.put("model", safe(item.getModel())); |
| | | map.put("quantity", item.getQuantity()); |
| | | map.put("defectivePhenomena", safe(item.getDefectivePhenomena())); |
| | | map.put("dealResult", safe(item.getDealResult())); |
| | | map.put("dealName", safe(item.getDealName())); |
| | | map.put("dealTime", formatDate(item.getDealTime())); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toMaterialItem(StockInventory item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("productModelId", item.getProductModelId()); |
| | | map.put("batchNo", safe(item.getBatchNo())); |
| | | map.put("qualitity", item.getQualitity()); |
| | | map.put("lockedQuantity", item.getLockedQuantity()); |
| | | map.put("warnNum", item.getWarnNum()); |
| | | map.put("lowStock", isLowStock(item)); |
| | | map.put("remark", safe(item.getRemark())); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> toExceptionItem(ProcurementExceptionRecord item) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("id", item.getId()); |
| | | map.put("purchaseLedgerId", item.getPurchaseLedgerId()); |
| | | map.put("exceptionReason", safe(item.getExceptionReason())); |
| | | map.put("exceptionNum", item.getExceptionNum()); |
| | | map.put("createTime", formatDateTime(item.getCreateTime())); |
| | | return map; |
| | | } |
| | | |
| | | private boolean isLowStock(StockInventory item) { |
| | | BigDecimal quantity = item.getQualitity(); |
| | | BigDecimal warnNum = item.getWarnNum(); |
| | | if (quantity == null || warnNum == null) { |
| | | return false; |
| | | } |
| | | return quantity.compareTo(warnNum) <= 0; |
| | | } |
| | | |
| | | private Map<String, Object> warningItem(String level, String title, long count, String detail) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("level", level); |
| | | map.put("title", title); |
| | | map.put("count", count); |
| | | map.put("detail", detail); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> actionCard(String code, |
| | | String name, |
| | | String method, |
| | | String targetApi, |
| | | List<String> requiredFields, |
| | | Map<String, Object> examplePayload, |
| | | String description) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("code", code); |
| | | map.put("name", name); |
| | | map.put("method", method); |
| | | map.put("targetApi", targetApi); |
| | | map.put("requiredFields", requiredFields); |
| | | map.put("examplePayload", examplePayload); |
| | | map.put("description", description); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> metric(String label, String value) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("label", label); |
| | | map.put("value", value); |
| | | return map; |
| | | } |
| | | |
| | | private Map<String, Object> rangeSummary(DateRange range, int count, String keyword) { |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("timeRange", range.label()); |
| | | summary.put("startDate", range.start().toString()); |
| | | summary.put("endDate", range.end().toString()); |
| | | summary.put("count", count); |
| | | summary.put("keyword", safe(keyword)); |
| | | return summary; |
| | | } |
| | | |
| | | private Map<String, Object> buildDomainBarOption(Map<String, Object> summary) { |
| | | List<String> xData = List.of("计å", "å·¥å", "设å¤", "è´¨é", "ç©æ", "å¼å¸¸"); |
| | | List<Number> yData = List.of( |
| | | numberValue(summary.get("planTotal")), |
| | | numberValue(summary.get("workOrderTotal")), |
| | | numberValue(summary.get("deviceTotal")), |
| | | numberValue(summary.get("qualityNgCount")), |
| | | numberValue(summary.get("lowStockCount")), |
| | | numberValue(summary.get("exceptionCount")) |
| | | ); |
| | | Map<String, Object> option = new LinkedHashMap<>(); |
| | | option.put("title", Map.of("text", "å¶é åå
³é®æ°é", "left", "center")); |
| | | option.put("tooltip", Map.of("trigger", "axis")); |
| | | option.put("xAxis", Map.of("type", "category", "data", xData)); |
| | | option.put("yAxis", Map.of("type", "value")); |
| | | option.put("series", List.of(Map.of("name", "æ°é", "type", "bar", "data", yData))); |
| | | return option; |
| | | } |
| | | |
| | | private Map<String, Object> buildQualityPieOption(long inspectTotal, long ngCount) { |
| | | long passCount = Math.max(inspectTotal - ngCount, 0); |
| | | List<Map<String, Object>> data = List.of( |
| | | Map.of("name", "ä¸åæ ¼", "value", ngCount), |
| | | Map.of("name", "éä¸åæ ¼", "value", passCount) |
| | | ); |
| | | Map<String, Object> option = new LinkedHashMap<>(); |
| | | option.put("title", Map.of("text", "è´¨éç»æåå¸", "left", "center")); |
| | | option.put("tooltip", Map.of("trigger", "item")); |
| | | option.put("series", List.of(Map.of("name", "è´¨é", "type", "pie", "radius", "60%", "data", data))); |
| | | return option; |
| | | } |
| | | |
| | | private int numberValue(Object value) { |
| | | if (value instanceof Number number) { |
| | | return number.intValue(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | private String toRate(long numerator, long denominator) { |
| | | if (denominator <= 0) { |
| | | return "0.00%"; |
| | | } |
| | | BigDecimal rate = new BigDecimal(numerator) |
| | | .multiply(new BigDecimal("100")) |
| | | .divide(new BigDecimal(denominator), 2, RoundingMode.HALF_UP); |
| | | return rate.toPlainString() + "%"; |
| | | } |
| | | |
| | | private String normalizeDomain(String domain) { |
| | | if (!StringUtils.hasText(domain)) { |
| | | return ""; |
| | | } |
| | | String value = domain.trim().toLowerCase(); |
| | | return switch (value) { |
| | | case "ç产ç°åº", "site", "factory", "workshop" -> "site"; |
| | | case "计å", "plan", "schedule" -> "plan"; |
| | | case "å·¥å", "workorder", "work_order", "task" -> "workorder"; |
| | | case "设å¤", "device", "equipment" -> "device"; |
| | | case "ç»´ä¿®", "repair", "maintenance" -> "repair"; |
| | | case "è´¨é", "quality", "qc" -> "quality"; |
| | | case "ç©æ", "material", "inventory", "stock" -> "material"; |
| | | case "å¼å¸¸", "exception", "abnormal" -> "exception"; |
| | | default -> value; |
| | | }; |
| | | } |
| | | |
| | | private boolean isRepairIntent(String keyword, String userQuery) { |
| | | String query = safe(userQuery); |
| | | return containsAny(safe(keyword), "ç»´ä¿®", "æ¥ä¿®", "æ£ä¿®", "ç»´æ¤") |
| | | || containsAny(query, "ç»´ä¿®", "æ¥ä¿®", "æ£ä¿®", "ç»´æ¤"); |
| | | } |
| | | |
| | | private String normalizeDeviceQueryKeyword(String keyword, String userQuery) { |
| | | String source = StringUtils.hasText(keyword) ? keyword : userQuery; |
| | | if (!StringUtils.hasText(source)) { |
| | | return null; |
| | | } |
| | | String cleaned = source |
| | | .replace("æ¥è¯¢", "") |
| | | .replace("æ¥ç", "") |
| | | .replace("帮æ", "") |
| | | .replace("请", "") |
| | | .replace("æ¥", "") |
| | | .replace("设å¤", "") |
| | | .replace("维修记å½", "") |
| | | .replace("ç»´ä¿®æ
åµ", "") |
| | | .replace("æ¥ä¿®è®°å½", "") |
| | | .replace("æ¥ä¿®æ
åµ", "") |
| | | .replace("ç»´ä¿®", "") |
| | | .replace("æ¥ä¿®", "") |
| | | .replace("æ
åµ", "") |
| | | .replace("è®°å½", "") |
| | | .replace("ä¿¡æ¯", "") |
| | | .replace("ç", "") |
| | | .replace("ä¸ä¸", "") |
| | | .trim(); |
| | | return cleaned.length() >= 2 ? cleaned : null; |
| | | } |
| | | |
| | | private List<Long> findDeviceLedgerIdsByKeyword(LoginUser loginUser, String keyword) { |
| | | if (!StringUtils.hasText(keyword)) { |
| | | return List.of(); |
| | | } |
| | | LambdaQueryWrapper<DeviceLedger> wrapper = new LambdaQueryWrapper<>(); |
| | | applyTenantFilter(wrapper, loginUser.getTenantId(), DeviceLedger::getTenantId); |
| | | Long currentDeptId = loginUser.getCurrentDeptId(); |
| | | if (currentDeptId != null) { |
| | | wrapper.and(w -> w.eq(DeviceLedger::getDeptId, currentDeptId).or().isNull(DeviceLedger::getDeptId)); |
| | | } |
| | | wrapper.and(w -> w.like(DeviceLedger::getDeviceName, keyword) |
| | | .or().like(DeviceLedger::getDeviceModel, keyword) |
| | | .or().like(DeviceLedger::getDeviceBrand, keyword)); |
| | | wrapper.orderByDesc(DeviceLedger::getId).last("limit 200"); |
| | | return defaultList(deviceLedgerMapper.selectList(wrapper)).stream() |
| | | .map(DeviceLedger::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | private boolean hasTimeConstraint(String startDate, String endDate, String userQuery) { |
| | | if (StringUtils.hasText(startDate) || StringUtils.hasText(endDate)) { |
| | | return true; |
| | | } |
| | | if (!StringUtils.hasText(userQuery)) { |
| | | return false; |
| | | } |
| | | String text = userQuery.trim(); |
| | | return containsAny(text, "ä»å¤©", "æ¨å¤©", "æ¬å¨", "ä¸å¨", "æ¬æ", "䏿", "ä»å¹´", "å»å¹´", "è¿", "æè¿"); |
| | | } |
| | | |
| | | private DateRange resolveDateRange(String startDate, String endDate, String timeRange) { |
| | | LocalDate today = LocalDate.now(); |
| | | LocalDate start = parseLocalDate(startDate); |
| | | LocalDate end = parseLocalDate(endDate); |
| | | if (start != null || end != null) { |
| | | LocalDate s = start != null ? start : end; |
| | | LocalDate e = end != null ? end : start; |
| | | if (s.isAfter(e)) { |
| | | LocalDate temp = s; |
| | | s = e; |
| | | e = temp; |
| | | } |
| | | return new DateRange(s, e, s + "è³" + e); |
| | | } |
| | | if (!StringUtils.hasText(timeRange)) { |
| | | return new DateRange(today.minusDays(29), today, "è¿30天"); |
| | | } |
| | | String text = timeRange.trim(); |
| | | if (text.contains("ä»å¤©")) { |
| | | return new DateRange(today, today, "ä»å¤©"); |
| | | } |
| | | if (text.contains("æ¬å¨")) { |
| | | LocalDate startOfWeek = today.minusDays(today.getDayOfWeek().getValue() - 1L); |
| | | return new DateRange(startOfWeek, today, "æ¬å¨"); |
| | | } |
| | | if (text.contains("æ¬æ")) { |
| | | return new DateRange(today.withDayOfMonth(1), today, "æ¬æ"); |
| | | } |
| | | if (text.contains("æ¬å¹´") || text.contains("ä»å¹´")) { |
| | | return new DateRange(today.withDayOfYear(1), today, "ä»å¹´"); |
| | | } |
| | | if (text.contains("å»å¹´")) { |
| | | LocalDate firstDay = today.minusYears(1).withDayOfYear(1); |
| | | LocalDate lastDay = today.minusYears(1).withMonth(12).withDayOfMonth(31); |
| | | return new DateRange(firstDay, lastDay, "å»å¹´"); |
| | | } |
| | | if (text.contains("䏿")) { |
| | | LocalDate startOfLastMonth = today.minusMonths(1).withDayOfMonth(1); |
| | | return new DateRange(startOfLastMonth, startOfLastMonth.withDayOfMonth(startOfLastMonth.lengthOfMonth()), "䏿"); |
| | | } |
| | | java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("(è¿|æè¿)(\\d+)(天|å¨|个æ|æ|å¹´)").matcher(text); |
| | | if (matcher.find()) { |
| | | int amount = Integer.parseInt(matcher.group(2)); |
| | | String unit = matcher.group(3); |
| | | LocalDate relativeStart = switch (unit) { |
| | | case "天" -> today.minusDays(Math.max(amount - 1L, 0)); |
| | | case "å¨" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1); |
| | | case "个æ", "æ" -> today.minusMonths(Math.max(amount, 1)).plusDays(1); |
| | | case "å¹´" -> today.minusYears(Math.max(amount, 1)).plusDays(1); |
| | | default -> today.minusDays(29); |
| | | }; |
| | | return new DateRange(relativeStart, today, "è¿" + amount + unit); |
| | | } |
| | | return new DateRange(today.minusDays(29), today, "è¿30天"); |
| | | } |
| | | |
| | | private LocalDate parseLocalDate(String text) { |
| | | if (!StringUtils.hasText(text)) { |
| | | return null; |
| | | } |
| | | return LocalDate.parse(text.trim(), DATE_FMT); |
| | | } |
| | | |
| | | private Date toDate(LocalDate date) { |
| | | return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()); |
| | | } |
| | | |
| | | private Date toExclusiveEndDate(LocalDate date) { |
| | | return Date.from(date.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()); |
| | | } |
| | | |
| | | private String formatDate(LocalDate date) { |
| | | return date == null ? "" : DATE_FMT.format(date); |
| | | } |
| | | |
| | | private String formatDate(Date date) { |
| | | if (date == null) { |
| | | return ""; |
| | | } |
| | | return DATE_FMT.format(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); |
| | | } |
| | | |
| | | private String formatDateTime(LocalDateTime time) { |
| | | if (time == null) { |
| | | return ""; |
| | | } |
| | | return time.truncatedTo(ChronoUnit.SECONDS).toString().replace('T', ' '); |
| | | } |
| | | |
| | | private int normalizeLimit(Integer limit) { |
| | | if (limit == null || limit <= 0) { |
| | | return DEFAULT_LIMIT; |
| | | } |
| | | return Math.min(limit, MAX_LIMIT); |
| | | } |
| | | |
| | | private boolean containsAny(String text, String... values) { |
| | | for (String value : values) { |
| | | if (text.contains(value)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private <T> void applyTenantFilter(LambdaQueryWrapper<T> wrapper, Long tenantId, SFunction<T, Long> field) { |
| | | if (tenantId != null) { |
| | | wrapper.eq(field, tenantId); |
| | | } |
| | | } |
| | | |
| | | private <T> void applyDeptFilter(LambdaQueryWrapper<T> wrapper, Long deptId, SFunction<T, Long> field) { |
| | | if (deptId != null) { |
| | | wrapper.eq(field, deptId); |
| | | } |
| | | } |
| | | |
| | | private LoginUser currentLoginUser(String memoryId) { |
| | | LoginUser loginUser = aiSessionUserContext.get(memoryId); |
| | | if (loginUser != null) { |
| | | return loginUser; |
| | | } |
| | | return SecurityUtils.getLoginUser(); |
| | | } |
| | | |
| | | private String safe(Object value) { |
| | | return value == null ? "" : String.valueOf(value).replace('\n', ' ').replace('\r', ' '); |
| | | } |
| | | |
| | | private <T> List<T> defaultList(List<T> list) { |
| | | return list == null ? List.of() : list; |
| | | } |
| | | |
| | | private String jsonResponse(boolean success, |
| | | String type, |
| | | String description, |
| | | Map<String, Object> summary, |
| | | Map<String, Object> data, |
| | | Map<String, Object> charts) { |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | result.put("success", success); |
| | | result.put("type", type); |
| | | result.put("description", description); |
| | | result.put("summary", summary == null ? Map.of() : summary); |
| | | result.put("data", data == null ? Map.of() : data); |
| | | result.put("charts", charts == null ? Map.of() : charts); |
| | | return JSON.toJSONString(result); |
| | | } |
| | | |
| | | private record DateRange(LocalDate start, LocalDate end, String label) { |
| | | } |
| | | } |
| | |
| | | */ |
| | | private BigDecimal maintenancePrice; |
| | | |
| | | private List<StorageBlobDTO> storageBlobDTOList; |
| | | private List<StorageBlobDTO> storageBlobDTOS; |
| | | } |
| | |
| | | if (shippingInfo != null) { |
| | | if (status.equals(2)) { |
| | | shippingInfo.setStatus("å®¡æ ¸éè¿"); |
| | | shippingInfo.setShippingDate(new Date()); |
| | | //æ´æ¹åºåºå®¡æ ¸ç¶æï¼å¾
ç¡®è®¤æ¹æå¾
å®¡æ ¸ï¼ |
| | | stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId()); |
| | | } else if (status.equals(3)) { |
| | | //å é¤åæ¬ï¼å¾
确认ï¼çåºåºå®¡æ ¸ç¶æ |
| | | stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode()); |
| | | shippingInfo.setStatus("å®¡æ ¸æç»"); |
| | | } else if (status.equals(1)) { |
| | | shippingInfo.setStatus("å®¡æ ¸ä¸"); |
| | |
| | | .collect(Collectors.joining(",")); |
| | | approveNodeService.initApproveNodes(nodeIdStr, no, approveProcessVO.getApproveDeptId()); |
| | | // éä»¶ç»å® |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_PROCESS, approveProcess.getId(), approveProcessVO.getStorageBlobDTOList()); |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_PROCESS, approveProcess.getId(), approveProcessVO.getStorageBlobDTOS()); |
| | | /*æ¶æ¯éç¥*/ |
| | | Long id = nodeIds.getFirst(); |
| | | if (approveProcess.getApproveType() == 8) { |
| | |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.production.bean.dto.ProductStructureDto; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.util.List; |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | public class ProductModelDto extends ProductModel { |
| | | private List<ProductStructureDto> productStructureList; |
| | |
| | | SALES_REFUND_AMOUNT_ORDER("sales_refund_amount_order"), |
| | | SALES_RECEIPT_RETURN("sales_receipt_return"), |
| | | ACCOUNT_EXPENSE("account_expense"), |
| | | FIN_VOUCHER("fin_voucher"), |
| | | ACCOUNT_FILE("account_file"); |
| | | |
| | | private final String type; |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.vo.ProductModelVo; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | |
| | | private String model; |
| | | |
| | | @Excel(name = "产åç¼ç ") |
| | | @TableField("product_code") |
| | | private String productCode; |
| | | |
| | | /** |
| | |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.sales.dto.LossProductModelDto; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.technology.mapper.TechnologyBomMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyBom; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | |
| | | private final ProductMapper productMapper; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final TechnologyBomMapper technologyBomMapper; |
| | | private ProductModelMapper productModelMapper; |
| | | |
| | | @Override |
| | | public int addOrEditProductModel(ProductModelDto productModelDto) { |
| | | String model = StringUtils.trim(productModelDto.getModel()); |
| | | String productCode = StringUtils.trim(productModelDto.getProductCode()); |
| | | productModelDto.setModel(model); |
| | | productModelDto.setProductCode(productCode); |
| | | checkModelAndProductCodeUnique(model, productCode, productModelDto.getId()); |
| | | |
| | | if (productModelDto.getId() == null) { |
| | | ProductModel productModel = new ProductModel(); |
| | |
| | | return productModelMapper.insert(productModel); |
| | | } else { |
| | | return productModelMapper.updateById(productModelDto); |
| | | } |
| | | } |
| | | |
| | | private void checkModelAndProductCodeUnique(String model, String productCode, Long currentId) { |
| | | if (StringUtils.isEmpty(model) || StringUtils.isEmpty(productCode)) { |
| | | return; |
| | | } |
| | | LambdaQueryWrapper<ProductModel> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(ProductModel::getModel, model) |
| | | .eq(ProductModel::getProductCode, productCode) |
| | | .ne(currentId != null, ProductModel::getId, currentId) |
| | | .last("limit 1"); |
| | | ProductModel duplicateProductModel = productModelMapper.selectOne(queryWrapper); |
| | | if (duplicateProductModel != null) { |
| | | throw new ServiceException("对åºçåå·" + model + "ç产åç¼ç " + productCode + "å·²ç»åå¨"); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | throw new RuntimeException("å·²ç»åå¨è¯¥äº§åçéå®å°è´¦åéè´å°è´¦"); |
| | | } |
| | | |
| | | // æ¯å¦åå¨BOM |
| | | List<TechnologyBom> technologyBoms = technologyBomMapper.selectList(new QueryWrapper<TechnologyBom>() |
| | | .lambda().in(TechnologyBom::getProductModelId, ids)); |
| | | if (CollectionUtils.isNotEmpty(technologyBoms)) { |
| | | throw new RuntimeException("å·²ç»åå¨è¯¥äº§åçBOMæ°æ®"); |
| | | } |
| | | |
| | | return productModelMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | } |
| | | |
| | |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.service.IProductService; |
| | | import com.ruoyi.basic.vo.ProductModelVo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | |
| | | if (ObjectUtils.isEmpty(productDto.getParentId())) { |
| | | throw new IllegalArgumentException("è¯·éæ©ç¶èç¹"); |
| | | } |
| | | String productName = StringUtils.trim(productDto.getProductName()); |
| | | if (StringUtils.isEmpty(productName)) { |
| | | throw new IllegalArgumentException("产ååç§°ä¸è½ä¸ºç©º"); |
| | | } |
| | | productDto.setProductName(productName); |
| | | checkProductNameUnique(productDto.getParentId(), productName, productDto.getId()); |
| | | if (productDto.getId() == null) { |
| | | // æ°å¢äº§åé»è¾ |
| | | if (productDto.getParentId() == null) { |
| | | // è¥æªæå®ç¶èç¹ï¼é»è®¤ä¸ºæ ¹èç¹ï¼parentId 设为 nullï¼ |
| | | productDto.setParentId(null); |
| | | } else { |
| | | // æ£æ¥ç¶èç¹æ¯å¦åå¨ï¼å¯éï¼æ ¹æ®ä¸å¡éæ±ï¼ |
| | | Product parent = productMapper.selectById(productDto.getParentId()); |
| | | if (parent == null) { |
| | | throw new IllegalArgumentException("ç¶èç¹ä¸åå¨ï¼æ æ³æ·»å å产å"); |
| | | } |
| | | // æ£æ¥ç¶èç¹æ¯å¦åå¨ï¼å¯éï¼æ ¹æ®ä¸å¡éæ±ï¼ |
| | | Product parent = productMapper.selectById(productDto.getParentId()); |
| | | if (parent == null) { |
| | | throw new IllegalArgumentException("ç¶èç¹ä¸åå¨ï¼æ æ³æ·»å å产å"); |
| | | } |
| | | return productMapper.insert(productDto); |
| | | } else { |
| | |
| | | } |
| | | } |
| | | |
| | | private void checkProductNameUnique(Long parentId, String productName, Long currentId) { |
| | | LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(Product::getParentId, parentId) |
| | | .eq(Product::getProductName, productName) |
| | | .ne(currentId != null, Product::getId, currentId) |
| | | .last("limit 1"); |
| | | Product duplicateProduct = productMapper.selectOne(queryWrapper); |
| | | if (duplicateProduct != null) { |
| | | throw new IllegalArgumentException("对åºç" + productName + "å·²ç»åå¨"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public int delProductByIds(Long[] ids) { |
| | | // 1. å é¤å表 product_model ä¸å
³èçæ°æ® |
| | |
| | | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.approve.pojo.KnowledgeBase; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.collaborativeApproval.dto.SealApplicationManagementDTO; |
| | | import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement; |
| | | import com.ruoyi.collaborativeApproval.service.SealApplicationManagementService; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | |
| | | public class SealApplicationManagementController { |
| | | private SealApplicationManagementService sealApplicationManagementService; |
| | | private ISysNoticeService sysNoticeService; |
| | | private FileUtil fileUtil; |
| | | |
| | | @GetMapping("/getList") |
| | | @Operation(summary = "å页æ¥è¯¢") |
| | |
| | | |
| | | @PostMapping("/add") |
| | | @Operation(summary = "æ°å¢") |
| | | public AjaxResult add(@RequestBody SealApplicationManagement sealApplicationManagement){ |
| | | public AjaxResult add(@RequestBody SealApplicationManagementDTO sealApplicationManagement){ |
| | | sealApplicationManagementService.save(sealApplicationManagement); |
| | | // 5. ä¿åéå®å°è´¦éä»¶ |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, |
| | | RecordTypeEnum.SEAL_APPLICATION_MANAGEMENT, |
| | | sealApplicationManagement.getId(), |
| | | sealApplicationManagement.getStorageBlobDTOs()); |
| | | //æ¶æ¯éç¥ |
| | | sysNoticeService.simpleNoticeByUser("ç¨å°å®¡æ¹", |
| | | "ç³è¯·ç¼å·ï¼"+sealApplicationManagement.getApplicationNum()+"\t" |
| | |
| | | |
| | | @PostMapping("/update") |
| | | @Operation(summary = "ä¿®æ¹") |
| | | public AjaxResult update(@RequestBody SealApplicationManagement sealApplicationManagement){ |
| | | public AjaxResult update(@RequestBody SealApplicationManagementDTO sealApplicationManagement){ |
| | | // 5. ä¿åéå®å°è´¦éä»¶ |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, |
| | | RecordTypeEnum.SEAL_APPLICATION_MANAGEMENT, |
| | | sealApplicationManagement.getId(), |
| | | sealApplicationManagement.getStorageBlobDTOs()); |
| | | return AjaxResult.success(sealApplicationManagementService.updateById(sealApplicationManagement)); |
| | | } |
| | | |
| | |
| | | if (CollectionUtils.isEmpty(ids)) { |
| | | throw new RuntimeException("è¯·ä¼ å
¥è¦å é¤çID"); |
| | | } |
| | | fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, |
| | | RecordTypeEnum.SEAL_APPLICATION_MANAGEMENT, |
| | | ids); |
| | | return AjaxResult.success(sealApplicationManagementService.removeBatchByIds(ids)); |
| | | } |
| | | |
| | |
| | | package com.ruoyi.collaborativeApproval.dto; |
| | | |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class SealApplicationManagementDTO extends SealApplicationManagement { |
| | |
| | | |
| | | //审æ¹äºº |
| | | private String approveUserName; |
| | | |
| | | private List<StorageBlobDTO> storageBlobDTOs; |
| | | private List<StorageBlobVO> storageBlobVOList; |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.collaborativeApproval.dto.SealApplicationManagementDTO; |
| | | import com.ruoyi.collaborativeApproval.mapper.SealApplicationManagementMapper; |
| | | import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement; |
| | |
| | | @RequiredArgsConstructor |
| | | public class SealApplicationManagementServiceImpl extends ServiceImpl<SealApplicationManagementMapper, SealApplicationManagement> implements SealApplicationManagementService { |
| | | private final SealApplicationManagementMapper sealApplicationManagementMapper; |
| | | private final FileUtil fileUtil; |
| | | |
| | | @Override |
| | | public IPage<SealApplicationManagementDTO> listPage(Page page, SealApplicationManagement sealApplicationManagement) { |
| | | return sealApplicationManagementMapper.listPage(page, sealApplicationManagement); |
| | | IPage<SealApplicationManagementDTO> sealApplicationManagementDTOIPage = sealApplicationManagementMapper.listPage(page, sealApplicationManagement); |
| | | sealApplicationManagementDTOIPage.getRecords().forEach(item -> { |
| | | item.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.SEAL_APPLICATION_MANAGEMENT, item.getId())); |
| | | }); |
| | | return sealApplicationManagementDTOIPage; |
| | | } |
| | | } |
| | |
| | | return deviceRepairService.updateDeviceRepair(deviceRepairDto); |
| | | } |
| | | |
| | | @PostMapping ("repair") |
| | | @PostMapping ("/repair") |
| | | @Operation(summary = "设å¤ç»´ä¿®") |
| | | public AjaxResult repair( @RequestBody DeviceRepairDto deviceRepairDto) { |
| | | return deviceRepairService.updateDeviceRepair(deviceRepairDto); |
| | | return deviceRepairService.confirmRepair(deviceRepairDto); |
| | | } |
| | | |
| | | @PostMapping ("/acceptance") |
| | | @Operation(summary = "è®¾å¤æ¥ä¿®éªæ¶å®¡æ¹") |
| | | public AjaxResult acceptance(@RequestBody DeviceRepairDto deviceRepairDto) { |
| | | return deviceRepairService.approveRepairAcceptance(deviceRepairDto); |
| | | } |
| | | |
| | | @DeleteMapping("/{ids}") |
| | |
| | | @Excel(name = "ç»´ä¿®ç»æ") |
| | | private String maintenanceResult; |
| | | |
| | | @Schema(description = "éªæ¶äºº") |
| | | @Excel(name = "éªæ¶äºº") |
| | | private String acceptanceName; |
| | | |
| | | @Schema(description = "éªæ¶æ¶é´") |
| | | @Excel(name = "éªæ¶æ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | private LocalDateTime acceptanceTime; |
| | | |
| | | @Schema(description = "éªæ¶å¤æ³¨") |
| | | @Excel(name = "éªæ¶å¤æ³¨") |
| | | private String acceptanceRemark; |
| | | |
| | | @Schema(description = "ç¶æ") |
| | | @Excel(name = "ç¶æ") |
| | | private String statusStr; |
| | |
| | | @Schema(description = "ç»´ä¿®ç»æ") |
| | | private String maintenanceResult; |
| | | |
| | | @Schema(description = "éªæ¶äºº") |
| | | private String acceptanceName; |
| | | |
| | | @Schema(description = "éªæ¶æ¶é´") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private LocalDateTime acceptanceTime; |
| | | |
| | | @Schema(description = "éªæ¶å¤æ³¨") |
| | | private String acceptanceRemark; |
| | | |
| | | @Schema(description = "ç¶æ 0 å¾
ç»´ä¿® 1å®ç» 2 失败") |
| | | // 0:å¾
ç»´ä¿® 1:å®ç» 2:失败 3:å¾
éªæ¶ |
| | | private Integer status; |
| | | |
| | | @Schema(description = "å建æ¶é´") |
| | |
| | | @Schema(description = "设å¤id") |
| | | private Long taskId; |
| | | |
| | | @Schema(description = "ä¿å
»äºº") |
| | | @Excel(name = "ä¿å
»äºº") |
| | | private String maintenancePerson; |
| | | |
| | | @Schema(description = "颿¬¡") |
| | | @Excel(name = "颿¬¡") |
| | | private String frequencyType; |
| | |
| | | |
| | | AjaxResult updateDeviceRepair(DeviceRepairDto deviceRepairDto); |
| | | |
| | | AjaxResult confirmRepair(DeviceRepairDto deviceRepairDto); |
| | | |
| | | AjaxResult approveRepairAcceptance(DeviceRepairDto deviceRepairDto); |
| | | |
| | | void export(HttpServletResponse response, Long[] ids); |
| | | |
| | | DeviceRepairVo detailById(Long id); |
| | |
| | | private final SparePartsRequisitionRecordService sparePartsRequisitionRecordService; |
| | | private final FileUtil fileUtil; |
| | | |
| | | private static final int STATUS_PENDING_REPAIR = 0; |
| | | private static final int STATUS_COMPLETED = 1; |
| | | private static final int STATUS_FAILED = 2; |
| | | private static final int STATUS_PENDING_ACCEPTANCE = 3; |
| | | |
| | | @Override |
| | | public IPage<DeviceRepairVo> queryPage(Page page, DeviceRepairDto deviceRepairDto) { |
| | | IPage<DeviceRepairVo> pageDto = deviceRepairMapper.queryPage(page, deviceRepairDto); |
| | |
| | | DeviceLedger byId = deviceLedgerService.getById(deviceRepairDto.getDeviceLedgerId()); |
| | | deviceRepairDto.setDeviceName(byId.getDeviceName()); |
| | | deviceRepairDto.setDeviceModel(byId.getDeviceModel()); |
| | | if (deviceRepairDto.getStatus() == null) { |
| | | deviceRepairDto.setStatus(STATUS_PENDING_REPAIR); |
| | | } |
| | | boolean save = this.save(deviceRepairDto); |
| | | if (save) { |
| | | // å¤çå¾çä¸ä¼ |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult updateDeviceRepair(DeviceRepairDto deviceRepairDto) { |
| | | DeviceRepair oldDeviceRepair = this.getById(deviceRepairDto.getId()); |
| | | if (oldDeviceRepair == null) { |
| | | return AjaxResult.error("æ¥ä¿®è®°å½ä¸åå¨"); |
| | | } |
| | | if (deviceRepairDto.getStatus() != null |
| | | && deviceRepairDto.getStatus() == STATUS_COMPLETED |
| | | && (oldDeviceRepair.getStatus() == null |
| | | || oldDeviceRepair.getStatus() != STATUS_COMPLETED)) { |
| | | return AjaxResult.error("请å
æäº¤éªæ¶å®¡æ¹ï¼éªæ¶éè¿åæå¯å®ç»"); |
| | | } |
| | | // å¤çå¤ä»¶ä½¿ç¨æ
åµ |
| | | if (CollectionUtils.isNotEmpty(deviceRepairDto.getSparePartsUseList())) { |
| | | List<Long> sparePartIds = new ArrayList<>(); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult confirmRepair(DeviceRepairDto deviceRepairDto) { |
| | | DeviceRepair oldDeviceRepair = this.getById(deviceRepairDto.getId()); |
| | | if (oldDeviceRepair == null) { |
| | | return AjaxResult.error("æ¥ä¿®è®°å½ä¸åå¨"); |
| | | } |
| | | if (oldDeviceRepair.getStatus() != null && oldDeviceRepair.getStatus() == STATUS_COMPLETED) { |
| | | return AjaxResult.error("该æ¥ä¿®å·²å®ç»ï¼ä¸è½éå¤ç¡®è®¤ç»´ä¿®"); |
| | | } |
| | | if (oldDeviceRepair.getStatus() != null && oldDeviceRepair.getStatus() == STATUS_PENDING_ACCEPTANCE) { |
| | | return AjaxResult.error("该æ¥ä¿®å·²æäº¤éªæ¶å®¡æ¹"); |
| | | } |
| | | deviceRepairDto.setStatus(STATUS_PENDING_ACCEPTANCE); |
| | | return updateDeviceRepair(deviceRepairDto); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult approveRepairAcceptance(DeviceRepairDto deviceRepairDto) { |
| | | if (deviceRepairDto.getId() == null) { |
| | | return AjaxResult.error("æ¥ä¿®è®°å½idä¸è½ä¸ºç©º"); |
| | | } |
| | | DeviceRepair oldDeviceRepair = this.getById(deviceRepairDto.getId()); |
| | | if (oldDeviceRepair == null) { |
| | | return AjaxResult.error("æ¥ä¿®è®°å½ä¸åå¨"); |
| | | } |
| | | if (oldDeviceRepair.getStatus() == null || oldDeviceRepair.getStatus() != STATUS_PENDING_ACCEPTANCE) { |
| | | return AjaxResult.error("该æ¥ä¿®æªè¿å
¥å¾
éªæ¶ç¶æï¼ä¸è½å®¡æ¹"); |
| | | } |
| | | if (StringUtils.isBlank(deviceRepairDto.getAcceptanceName())) { |
| | | return AjaxResult.error("éªæ¶äººä¸è½ä¸ºç©º"); |
| | | } |
| | | if (deviceRepairDto.getAcceptanceTime() == null) { |
| | | return AjaxResult.error("éªæ¶æ¶é´ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isBlank(deviceRepairDto.getAcceptanceRemark())) { |
| | | return AjaxResult.error("éªæ¶å¤æ³¨ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | DeviceRepair update = new DeviceRepair(); |
| | | update.setId(deviceRepairDto.getId()); |
| | | update.setAcceptanceName(deviceRepairDto.getAcceptanceName()); |
| | | update.setAcceptanceTime(deviceRepairDto.getAcceptanceTime()); |
| | | update.setAcceptanceRemark(deviceRepairDto.getAcceptanceRemark()); |
| | | update.setStatus(STATUS_COMPLETED); |
| | | if (this.updateById(update)) { |
| | | return AjaxResult.success(); |
| | | } |
| | | return AjaxResult.error("éªæ¶å®¡æ¹å¤±è´¥"); |
| | | } |
| | | |
| | | @Override |
| | | public void export(HttpServletResponse response, Long[] ids) { |
| | | if (ids == null || ids.length == 0) { |
| | | List<DeviceRepair> supplierManageList = this.list(); |
| | |
| | | supplierManageList.stream().forEach(deviceRepair -> { |
| | | DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto(); |
| | | BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto); |
| | | deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾
ç»´ä¿®" : deviceRepair.getStatus() == 1 ? "å®ç»" : "失败"); |
| | | |
| | | deviceRepairExeclDto.setStatusStr(resolveStatusText(deviceRepair.getStatus())); |
| | | deviceLedgerExeclDtos.add(deviceRepairExeclDto); |
| | | }); |
| | | ExcelUtil<DeviceRepairExeclDto> util = new ExcelUtil<DeviceRepairExeclDto>(DeviceRepairExeclDto.class); |
| | | util.exportExcel(response, deviceLedgerExeclDtos, "è®¾å¤æ¥ä¿®å¯¼åº"); |
| | | }else { |
| | | ArrayList<Long> arrayList = new ArrayList<>(); |
| | | Arrays.stream(ids).map(id -> { |
| | | return arrayList.add( id); |
| | | }); |
| | | ArrayList<Long> arrayList = new ArrayList<>(Arrays.asList(ids)); |
| | | List<DeviceRepair> supplierManageList = deviceRepairMapper.selectBatchIds(arrayList); |
| | | ArrayList<DeviceRepairExeclDto> deviceLedgerExeclDtos = new ArrayList<>(); |
| | | supplierManageList.stream().forEach(deviceRepair -> { |
| | | DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto(); |
| | | BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto); |
| | | deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾
ç»´ä¿®" : deviceRepair.getStatus() == 1 ? "å®ç»" : "失败"); |
| | | |
| | | deviceRepairExeclDto.setStatusStr(resolveStatusText(deviceRepair.getStatus())); |
| | | deviceLedgerExeclDtos.add(deviceRepairExeclDto); |
| | | }); |
| | | ExcelUtil<DeviceRepairExeclDto> util = new ExcelUtil<DeviceRepairExeclDto>(DeviceRepairExeclDto.class); |
| | |
| | | |
| | | } |
| | | |
| | | private String resolveStatusText(Integer status) { |
| | | if (status == null) { |
| | | return ""; |
| | | } |
| | | if (status == STATUS_PENDING_REPAIR) { |
| | | return "å¾
ç»´ä¿®"; |
| | | } |
| | | if (status == STATUS_COMPLETED) { |
| | | return "å®ç»"; |
| | | } |
| | | if (status == STATUS_FAILED) { |
| | | return "失败"; |
| | | } |
| | | if (status == STATUS_PENDING_ACCEPTANCE) { |
| | | return "å¾
éªæ¶"; |
| | | } |
| | | return "æªç¥"; |
| | | } |
| | | |
| | | @Override |
| | | public DeviceRepairVo detailById(Long id) { |
| | | DeviceRepairVo vo = deviceRepairMapper.detailById(id); |
| | |
| | | inspectionTask.setMaintenanceTaskId(timingTask.getId()); |
| | | inspectionTask.setDeviceLedgerId(timingTask.getTaskId()); |
| | | inspectionTask.setMaintenancePlanTime(LocalDateTime.now()); |
| | | inspectionTask.setMaintenanceActuallyName(timingTask.getMaintenancePerson()); |
| | | inspectionTask.setFrequencyType(timingTask.getFrequencyType()); |
| | | inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); |
| | | inspectionTask.setTenantId(timingTask.getTenantId()); |
| | |
| | | public void setUser(SysUser user) |
| | | { |
| | | this.user = user; |
| | | this.aiEnabled = user == null ? null : user.getAiEnabled(); |
| | | if (user != null && user.getAiEnabled() != null) |
| | | { |
| | | this.aiEnabled = user.getAiEnabled(); |
| | | } |
| | | } |
| | |
|
| | | @Override
|
| | |
| | | @Excel(name = "å·¡æ£ä»»å¡åç§°") |
| | | private String taskName; |
| | | |
| | | @Schema(description = "å·¡æ£é¡¹ç®") |
| | | @Excel(name = "å·¡æ£é¡¹ç®") |
| | | private String inspectionProject; |
| | | |
| | | @Schema(description = "设å¤id") |
| | | private Integer taskId; |
| | | |
| | |
| | | @Excel(name = "夿³¨") |
| | | private String remarks; |
| | | |
| | | @Schema(description = "å·¡æ£ç»æ 0 å¼å¸¸ 1 æ£å¸¸") |
| | | private String inspectionResult; |
| | | |
| | | @Schema(description = "å¼å¸¸æè¿°") |
| | | private String abnormalDescription; |
| | | |
| | | @Schema(description = "å
³èç»´ä¿®åID") |
| | | private Long deviceRepairId; |
| | | |
| | | @Schema(description = "éªæ¶äººID") |
| | | private Long acceptanceUserId; |
| | | |
| | | @Schema(description = "éªæ¶äºº") |
| | | @Excel(name = "éªæ¶äºº") |
| | | private String acceptanceName; |
| | | |
| | | @Schema(description = "ä»»å¡ç»è®°äººID") |
| | | private Long registrantId; |
| | | |
| | |
| | | @Excel(name = "å·¡æ£ä»»å¡åç§°") |
| | | private String taskName; |
| | | |
| | | @Schema(description = "å·¡æ£é¡¹ç®") |
| | | @Excel(name = "å·¡æ£é¡¹ç®") |
| | | private String inspectionProject; |
| | | |
| | | @Schema(description = "设å¤id") |
| | | private Integer taskId; |
| | | |
| | |
| | | @Schema(description = "æ¯å¦æ¿æ´»") |
| | | private boolean isActive; |
| | | |
| | | @Schema(description = "æ¯å¦å¯ç¨ 0å¦ 1æ¯") |
| | | @Excel(name = "æ¯å¦å¯ç¨", readConverterExp = "0=å¦,1=æ¯") |
| | | private Integer isEnabled; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | @Excel(name = "夿³¨") |
| | | private String remarks; |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.dto.StorageBlobDTO; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.device.mapper.DeviceLedgerMapper; |
| | | import com.ruoyi.device.mapper.DeviceRepairMapper; |
| | | import com.ruoyi.device.pojo.DeviceLedger; |
| | | import com.ruoyi.device.pojo.DeviceRepair; |
| | | import com.ruoyi.inspectiontask.dto.InspectionTaskDto; |
| | | import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; |
| | | import com.ruoyi.inspectiontask.pojo.InspectionTask; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Date; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | |
| | | |
| | | private final FileUtil fileUtil; |
| | | |
| | | private final DeviceRepairMapper deviceRepairMapper; |
| | | |
| | | private final DeviceLedgerMapper deviceLedgerMapper; |
| | | |
| | | private static final String INSPECTION_RESULT_ABNORMAL = "0"; |
| | | private static final String INSPECTION_RESULT_NORMAL = "1"; |
| | | private static final int REPAIR_STATUS_PENDING = 0; |
| | | |
| | | @Override |
| | | public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) { |
| | | LambdaQueryWrapper<InspectionTask> queryWrapper = new LambdaQueryWrapper<>(); |
| | |
| | | if (StringUtils.isNotBlank(inspectionTaskDto.getTaskName())) { |
| | | queryWrapper.like(InspectionTask::getTaskName, inspectionTaskDto.getTaskName()); |
| | | } |
| | | if (StringUtils.isNotBlank(inspectionTaskDto.getInspectionProject())) { |
| | | queryWrapper.like(InspectionTask::getInspectionProject, inspectionTaskDto.getInspectionProject()); |
| | | } |
| | | IPage<InspectionTask> entityPage = inspectionTaskMapper.selectPage(page, queryWrapper); |
| | | |
| | | // æ æ°æ®æåè¿å |
| | | if (CollectionUtils.isEmpty(entityPage.getRecords())) { |
| | | return new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal()); |
| | | } |
| | | // è·åidéå |
| | | List<Long> ids = entityPage.getRecords().stream().map(InspectionTask::getId).collect(Collectors.toList()); |
| | | //ç»è®°äººids |
| | | List<Long> registrantIds = entityPage.getRecords().stream().map(InspectionTask::getRegistrantId).collect(Collectors.toList()); |
| | | // æ¹éæ¥è¯¢ç»è®°äºº |
| | |
| | | } else { |
| | | sysUserMap = new HashMap<>(); |
| | | } |
| | | //å·¡æ£äººids |
| | | List<String> inspectorIds = entityPage.getRecords().stream().map(InspectionTask::getInspectorId).collect(Collectors.toList()); |
| | | |
| | | //è·åææä¸éå¤çç¨æ·ID |
| | | Set<Long> allUserIds = entityPage.getRecords().stream() |
| | | .map(InspectionTask::getInspectorId) // è·å"2,3"è¿æ ·çå符串 |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) { |
| | | InspectionTask oldInspectionTask = null; |
| | | if (Objects.nonNull(inspectionTaskDto.getId())) { |
| | | oldInspectionTask = inspectionTaskMapper.selectById(inspectionTaskDto.getId()); |
| | | if (oldInspectionTask == null) { |
| | | throw new IllegalArgumentException("å·¡æ£ä»»å¡ä¸åå¨"); |
| | | } |
| | | } |
| | | validateInspectionInput(inspectionTaskDto, oldInspectionTask); |
| | | |
| | | InspectionTask inspectionTask = new InspectionTask(); |
| | | BeanUtils.copyProperties(inspectionTaskDto, inspectionTask); |
| | | inspectionTask.setRegistrantId(SecurityUtils.getLoginUser().getUserId()); |
| | | inspectionTask.setRegistrant(SecurityUtils.getLoginUser().getUsername()); |
| | | fillAcceptanceInfo(inspectionTask, oldInspectionTask); |
| | | int i; |
| | | if (Objects.isNull(inspectionTaskDto.getId())) { |
| | | i = inspectionTaskMapper.insert(inspectionTask); |
| | | } else { |
| | | i = inspectionTaskMapper.updateById(inspectionTask); |
| | | } |
| | | // ä¿åæä»¶ |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListDTO()); |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.AFTER_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListAfterDTO()); |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.BEFORE_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListBeforeDTO()); |
| | | if (i <= 0) { |
| | | return i; |
| | | } |
| | | Long linkedRepairId = syncRepairOrderIfAbnormal(inspectionTask, oldInspectionTask); |
| | | if (linkedRepairId != null && !Objects.equals(linkedRepairId, inspectionTask.getDeviceRepairId())) { |
| | | InspectionTask relationUpdate = new InspectionTask(); |
| | | relationUpdate.setId(inspectionTask.getId()); |
| | | relationUpdate.setDeviceRepairId(linkedRepairId); |
| | | inspectionTaskMapper.updateById(relationUpdate); |
| | | inspectionTask.setDeviceRepairId(linkedRepairId); |
| | | } |
| | | // ä¿åæä»¶ï¼å段ä¸ä¼ åä¿çåå²ï¼ |
| | | saveInspectionAttachments(inspectionTask.getId(), inspectionTaskDto); |
| | | |
| | | return i; |
| | | } |
| | | |
| | | private void validateInspectionInput(InspectionTaskDto inspectionTaskDto, InspectionTask oldInspectionTask) { |
| | | String inspectionResult = inspectionTaskDto.getInspectionResult(); |
| | | if (StringUtils.isBlank(inspectionResult) && oldInspectionTask != null) { |
| | | inspectionResult = oldInspectionTask.getInspectionResult(); |
| | | } |
| | | if (StringUtils.isBlank(inspectionResult)) { |
| | | throw new IllegalArgumentException("è¯·éæ©å·¡æ£ç»æ"); |
| | | } |
| | | if (!INSPECTION_RESULT_ABNORMAL.equals(inspectionResult) && !INSPECTION_RESULT_NORMAL.equals(inspectionResult)) { |
| | | throw new IllegalArgumentException("å·¡æ£ç»æä»
æ¯æï¼0-å¼å¸¸ï¼1-æ£å¸¸"); |
| | | } |
| | | inspectionTaskDto.setInspectionResult(inspectionResult); |
| | | |
| | | if (!INSPECTION_RESULT_ABNORMAL.equals(inspectionResult)) { |
| | | return; |
| | | } |
| | | |
| | | String abnormalDescription = inspectionTaskDto.getAbnormalDescription(); |
| | | if (StringUtils.isBlank(abnormalDescription) && oldInspectionTask != null) { |
| | | abnormalDescription = oldInspectionTask.getAbnormalDescription(); |
| | | } |
| | | if (StringUtils.isBlank(abnormalDescription)) { |
| | | throw new IllegalArgumentException("å·¡æ£ç»æä¸ºå¼å¸¸æ¶ï¼å¼å¸¸æè¿°ä¸è½ä¸ºç©º"); |
| | | } |
| | | inspectionTaskDto.setAbnormalDescription(abnormalDescription); |
| | | |
| | | if (!hasAnyInspectionPhotoAfterSave(inspectionTaskDto, oldInspectionTask)) { |
| | | throw new IllegalArgumentException("å·¡æ£ç»æä¸ºå¼å¸¸æ¶ï¼å¿
é¡»ä¸ä¼ è³å°ä¸å¼ ç
§ç"); |
| | | } |
| | | } |
| | | |
| | | private boolean hasAnyInspectionPhotoAfterSave(InspectionTaskDto inspectionTaskDto, InspectionTask oldInspectionTask) { |
| | | Long recordId = oldInspectionTask == null ? null : oldInspectionTask.getId(); |
| | | return hasApplicationPhotoAfterSave(inspectionTaskDto.getCommonFileListDTO(), ApplicationTypeEnum.FILE, recordId) |
| | | || hasApplicationPhotoAfterSave(inspectionTaskDto.getCommonFileListAfterDTO(), ApplicationTypeEnum.AFTER_FILE, recordId) |
| | | || hasApplicationPhotoAfterSave(inspectionTaskDto.getCommonFileListBeforeDTO(), ApplicationTypeEnum.BEFORE_FILE, recordId); |
| | | } |
| | | |
| | | private boolean hasApplicationPhotoAfterSave(List<StorageBlobDTO> requestPhotos, ApplicationTypeEnum applicationType, Long recordId) { |
| | | if (requestPhotos != null) { |
| | | return !requestPhotos.isEmpty(); |
| | | } |
| | | if (recordId == null) { |
| | | return false; |
| | | } |
| | | return CollectionUtils.isNotEmpty(fileUtil.getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(applicationType, RecordTypeEnum.INSPECTION_TASK, recordId)); |
| | | } |
| | | |
| | | private void fillAcceptanceInfo(InspectionTask inspectionTask, InspectionTask oldInspectionTask) { |
| | | Long acceptanceUserId = inspectionTask.getAcceptanceUserId(); |
| | | if (acceptanceUserId == null && oldInspectionTask != null) { |
| | | acceptanceUserId = oldInspectionTask.getAcceptanceUserId(); |
| | | } |
| | | if (acceptanceUserId != null) { |
| | | inspectionTask.setAcceptanceUserId(acceptanceUserId); |
| | | } |
| | | |
| | | String acceptanceName = inspectionTask.getAcceptanceName(); |
| | | if (StringUtils.isBlank(acceptanceName) && acceptanceUserId != null) { |
| | | SysUser acceptanceUser = sysUserMapper.selectUserById(acceptanceUserId); |
| | | if (acceptanceUser != null) { |
| | | acceptanceName = acceptanceUser.getNickName(); |
| | | } |
| | | } |
| | | if (StringUtils.isBlank(acceptanceName) && oldInspectionTask != null) { |
| | | acceptanceName = oldInspectionTask.getAcceptanceName(); |
| | | } |
| | | inspectionTask.setAcceptanceName(acceptanceName); |
| | | } |
| | | |
| | | private Long syncRepairOrderIfAbnormal(InspectionTask inspectionTask, InspectionTask oldInspectionTask) { |
| | | if (!INSPECTION_RESULT_ABNORMAL.equals(inspectionTask.getInspectionResult())) { |
| | | return inspectionTask.getDeviceRepairId(); |
| | | } |
| | | Long linkedRepairId = inspectionTask.getDeviceRepairId(); |
| | | if (linkedRepairId == null && oldInspectionTask != null) { |
| | | linkedRepairId = oldInspectionTask.getDeviceRepairId(); |
| | | } |
| | | |
| | | if (linkedRepairId != null) { |
| | | DeviceRepair updateRepair = new DeviceRepair(); |
| | | updateRepair.setId(linkedRepairId); |
| | | updateRepair.setRemark(inspectionTask.getAbnormalDescription()); |
| | | deviceRepairMapper.updateById(updateRepair); |
| | | return linkedRepairId; |
| | | } |
| | | |
| | | DeviceRepair deviceRepair = buildDeviceRepair(inspectionTask, oldInspectionTask); |
| | | deviceRepairMapper.insert(deviceRepair); |
| | | return deviceRepair.getId(); |
| | | } |
| | | |
| | | private DeviceRepair buildDeviceRepair(InspectionTask inspectionTask, InspectionTask oldInspectionTask) { |
| | | DeviceRepair deviceRepair = new DeviceRepair(); |
| | | Long deviceLedgerId = resolveDeviceLedgerId(inspectionTask, oldInspectionTask); |
| | | DeviceLedger deviceLedger = resolveDeviceLedger(deviceLedgerId); |
| | | deviceRepair.setDeviceLedgerId(deviceLedgerId); |
| | | deviceRepair.setDeviceName(resolveDeviceName(inspectionTask, oldInspectionTask, deviceLedger)); |
| | | deviceRepair.setDeviceModel(deviceLedger == null ? null : deviceLedger.getDeviceModel()); |
| | | deviceRepair.setRepairName(resolveRepairReporter(inspectionTask, oldInspectionTask)); |
| | | deviceRepair.setRepairTime(new Date()); |
| | | deviceRepair.setRemark(inspectionTask.getAbnormalDescription()); |
| | | deviceRepair.setMachineryCategory(deviceLedger == null ? null : deviceLedger.getType()); |
| | | deviceRepair.setStatus(REPAIR_STATUS_PENDING); |
| | | return deviceRepair; |
| | | } |
| | | |
| | | private Long resolveDeviceLedgerId(InspectionTask inspectionTask, InspectionTask oldInspectionTask) { |
| | | Integer taskId = inspectionTask.getTaskId(); |
| | | if (taskId == null && oldInspectionTask != null) { |
| | | taskId = oldInspectionTask.getTaskId(); |
| | | } |
| | | if (taskId == null || taskId <= 0) { |
| | | return null; |
| | | } |
| | | return taskId.longValue(); |
| | | } |
| | | |
| | | private DeviceLedger resolveDeviceLedger(Long deviceLedgerId) { |
| | | if (deviceLedgerId == null) { |
| | | return null; |
| | | } |
| | | return deviceLedgerMapper.selectById(deviceLedgerId); |
| | | } |
| | | |
| | | private String resolveDeviceName(InspectionTask inspectionTask, InspectionTask oldInspectionTask, DeviceLedger deviceLedger) { |
| | | String taskName = inspectionTask.getTaskName(); |
| | | if (StringUtils.isBlank(taskName) && oldInspectionTask != null) { |
| | | taskName = oldInspectionTask.getTaskName(); |
| | | } |
| | | if (StringUtils.isNotBlank(taskName)) { |
| | | return taskName; |
| | | } |
| | | return deviceLedger == null ? null : deviceLedger.getDeviceName(); |
| | | } |
| | | |
| | | private String resolveRepairReporter(InspectionTask inspectionTask, InspectionTask oldInspectionTask) { |
| | | String reporter = inspectionTask.getInspector(); |
| | | if (StringUtils.isBlank(reporter) && oldInspectionTask != null) { |
| | | reporter = oldInspectionTask.getInspector(); |
| | | } |
| | | if (StringUtils.isNotBlank(reporter)) { |
| | | return reporter; |
| | | } |
| | | String inspectorNameByUserId = resolveInspectorNameByUserId(inspectionTask.getInspectorId()); |
| | | if (StringUtils.isBlank(inspectorNameByUserId) && oldInspectionTask != null) { |
| | | inspectorNameByUserId = resolveInspectorNameByUserId(oldInspectionTask.getInspectorId()); |
| | | } |
| | | if (StringUtils.isNotBlank(inspectorNameByUserId)) { |
| | | return inspectorNameByUserId; |
| | | } |
| | | try { |
| | | return SecurityUtils.getUsername(); |
| | | } catch (Exception ignored) { |
| | | return "system"; |
| | | } |
| | | } |
| | | |
| | | private String resolveInspectorNameByUserId(String inspectorIds) { |
| | | if (StringUtils.isBlank(inspectorIds)) { |
| | | return null; |
| | | } |
| | | String firstInspectorId = Arrays.stream(inspectorIds.split(",")) |
| | | .map(String::trim) |
| | | .filter(StringUtils::isNotBlank) |
| | | .findFirst() |
| | | .orElse(null); |
| | | if (!StringUtils.isNumeric(firstInspectorId)) { |
| | | return null; |
| | | } |
| | | SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(firstInspectorId)); |
| | | return sysUser == null ? null : sysUser.getNickName(); |
| | | } |
| | | |
| | | private void saveInspectionAttachments(Long inspectionTaskId, InspectionTaskDto inspectionTaskDto) { |
| | | saveAttachmentIfPresent(inspectionTaskId, ApplicationTypeEnum.FILE, inspectionTaskDto.getCommonFileListDTO()); |
| | | saveAttachmentIfPresent(inspectionTaskId, ApplicationTypeEnum.AFTER_FILE, inspectionTaskDto.getCommonFileListAfterDTO()); |
| | | saveAttachmentIfPresent(inspectionTaskId, ApplicationTypeEnum.BEFORE_FILE, inspectionTaskDto.getCommonFileListBeforeDTO()); |
| | | } |
| | | |
| | | private void saveAttachmentIfPresent(Long inspectionTaskId, ApplicationTypeEnum applicationTypeEnum, List<StorageBlobDTO> storageBlobDTOS) { |
| | | if (storageBlobDTOS == null) { |
| | | return; |
| | | } |
| | | fileUtil.saveStorageAttachment(applicationTypeEnum, RecordTypeEnum.INSPECTION_TASK, inspectionTaskId, storageBlobDTOS); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int delByIds(Long[] ids) { |
| | |
| | | import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; |
| | | import com.ruoyi.inspectiontask.pojo.InspectionTask; |
| | | import com.ruoyi.inspectiontask.pojo.TimingTask; |
| | | import lombok.RequiredArgsConstructor; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import org.quartz.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.jdbc.core.BeanPropertyRowMapper; |
| | |
| | | TimingTask timingTask = tasks.isEmpty() ? null : tasks.get(0); |
| | | if (timingTask == null) { |
| | | throw new JobExecutionException("æ¾ä¸å°å®æ¶ä»»å¡: " + taskId); |
| | | } |
| | | if (timingTask.getIsEnabled() != null && timingTask.getIsEnabled() == 0) { |
| | | return; |
| | | } |
| | | |
| | | // if (!timingTask.isActive()) { |
| | |
| | | |
| | | // å¤å¶åºæ¬å±æ§ |
| | | inspectionTask.setTaskName(timingTask.getTaskName()); |
| | | inspectionTask.setInspectionProject(timingTask.getInspectionProject()); |
| | | inspectionTask.setTaskId(timingTask.getTaskId()); |
| | | inspectionTask.setInspectorId(timingTask.getInspectorIds()); |
| | | inspectionTask.setInspectionLocation(timingTask.getInspectionLocation()); |
| | | inspectionTask.setRemarks("èªå¨çæèªå®æ¶ä»»å¡ID: " + timingTask.getId()); |
| | | String remarks = "èªå¨çæèªå®æ¶ä»»å¡ID: " + timingTask.getId(); |
| | | if (StringUtils.isNotBlank(timingTask.getRemarks())) { |
| | | remarks = remarks + "ï¼" + timingTask.getRemarks(); |
| | | } |
| | | inspectionTask.setRemarks(remarks); |
| | | inspectionTask.setRegistrantId(timingTask.getRegistrantId()); |
| | | inspectionTask.setFrequencyType(timingTask.getFrequencyType()); |
| | | inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); |
| | |
| | | private final TimingTaskMapper timingTaskMapper; |
| | | private final TimingTaskScheduler timingTaskScheduler; |
| | | private final SysUserMapper sysUserMapper; |
| | | private static final int ENABLED = 1; |
| | | private static final int DISABLED = 0; |
| | | |
| | | |
| | | @Override |
| | |
| | | LambdaQueryWrapper<TimingTask> queryWrapper = new LambdaQueryWrapper<>(); |
| | | if (StringUtils.isNotBlank(timingTask.getTaskName())) { |
| | | queryWrapper.like(TimingTask::getTaskName, timingTask.getTaskName()); |
| | | } |
| | | if (StringUtils.isNotBlank(timingTask.getInspectionProject())) { |
| | | queryWrapper.like(TimingTask::getInspectionProject, timingTask.getInspectionProject()); |
| | | } |
| | | if (timingTask.getIsEnabled() != null) { |
| | | queryWrapper.eq(TimingTask::getIsEnabled, timingTask.getIsEnabled()); |
| | | } |
| | | IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper); |
| | | |
| | |
| | | @Override |
| | | @Transactional |
| | | public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException { |
| | | TimingTask oldTimingTask = null; |
| | | if (Objects.nonNull(timingTaskDto.getId())) { |
| | | oldTimingTask = timingTaskMapper.selectById(timingTaskDto.getId()); |
| | | if (oldTimingTask == null) { |
| | | throw new IllegalArgumentException("宿¶ä»»å¡ä¸åå¨"); |
| | | } |
| | | } |
| | | TimingTask timingTask = new TimingTask(); |
| | | BeanUtils.copyProperties(timingTaskDto, timingTask); |
| | | timingTask.setIsEnabled(resolveEnabledValue(timingTask.getIsEnabled(), oldTimingTask)); |
| | | timingTask.setActive(ENABLED == timingTask.getIsEnabled()); |
| | | // 1. è§£æå符串为 LocalDateï¼åªå
å«å¹´ææ¥ï¼ |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | LocalDate localDate = LocalDate.now(); |
| | |
| | | // 设置å建人信æ¯åé»è®¤å¼ |
| | | if (Objects.isNull(timingTaskDto.getId())) { |
| | | timingTask.setRegistrationDate(LocalDate.now()); |
| | | timingTask.setActive(true); |
| | | |
| | | // 计ç®é¦æ¬¡æ§è¡æ¶é´ |
| | | LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask); |
| | | timingTask.setNextExecutionTime(firstExecutionTime); |
| | | int result = timingTaskMapper.insert(timingTask); |
| | | if (result > 0) { |
| | | if (result > 0 && isEnabled(timingTask.getIsEnabled(), timingTask.isActive())) { |
| | | // æ°å¢æååæ·»å å°è°åº¦å¨ |
| | | timingTaskScheduler.scheduleTimingTask(timingTask); |
| | | } |
| | |
| | | |
| | | int result = timingTaskMapper.updateById(timingTask); |
| | | if (result > 0) { |
| | | // æ´æ°æååéæ°è°åº¦ä»»å¡ |
| | | timingTaskScheduler.rescheduleTimingTask(timingTask); |
| | | boolean oldEnabled = isEnabled(oldTimingTask == null ? null : oldTimingTask.getIsEnabled(), oldTimingTask != null && oldTimingTask.isActive()); |
| | | boolean newEnabled = isEnabled(timingTask.getIsEnabled(), timingTask.isActive()); |
| | | if (!newEnabled) { |
| | | timingTaskScheduler.unscheduleTimingTask(timingTask.getId()); |
| | | } else if (oldEnabled) { |
| | | // æ´æ°æååéæ°è°åº¦ä»»å¡ |
| | | timingTaskScheduler.rescheduleTimingTask(timingTask); |
| | | } else { |
| | | // ä»ç¦ç¨æ¹ä¸ºå¯ç¨æ¶éæ°å建è°åº¦ä»»å¡ |
| | | timingTaskScheduler.scheduleTimingTask(timingTask); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | |
| | | return days; |
| | | } |
| | | |
| | | private Integer resolveEnabledValue(Integer requestEnabled, TimingTask oldTimingTask) { |
| | | if (requestEnabled != null) { |
| | | return requestEnabled; |
| | | } |
| | | if (oldTimingTask != null) { |
| | | if (oldTimingTask.getIsEnabled() != null) { |
| | | return oldTimingTask.getIsEnabled(); |
| | | } |
| | | return oldTimingTask.isActive() ? ENABLED : DISABLED; |
| | | } |
| | | return ENABLED; |
| | | } |
| | | |
| | | private boolean isEnabled(Integer enabledValue, boolean activeFallback) { |
| | | if (enabledValue != null) { |
| | | return ENABLED == enabledValue; |
| | | } |
| | | return activeFallback; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/Details.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/InventoryInformationDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementAddDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementManagementUpdateDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutAdd.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutPageDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ProcurementUpdateDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| ÎļþÃû´Ó src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java ÐÞ¸Ä |
| | |
| | | package com.ruoyi.procurementrecord.dto; |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnManagement; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.procurementrecord.bean.dto; |
| | | |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Data |
| | | public class ReturnSaleProductDto extends ReturnSaleProduct { |
| | | |
| | | private String productName; |
| | | |
| | | private String model; |
| | | |
| | | private String unit; |
| | | |
| | | //æªéè´§æ°é |
| | | private BigDecimal unQuantity; |
| | | |
| | | //æ»éè´§æ°é |
| | | private BigDecimal totalReturnNum; |
| | | |
| | | // éè´§æ»ä»· |
| | | private BigDecimal price; |
| | | |
| | | // éè´§æ»ä»· |
| | | private BigDecimal taxInclusiveUnitPrice; |
| | | |
| | | @Schema(description = "åºåºåå·") |
| | | private String outboundBatches; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·") |
| | | private String batchNo; |
| | | |
| | | @Schema(description = "åè´§åºåºæ°é") |
| | | private BigDecimal stockOutNum; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.procurementrecord.bean.vo; |
| | | |
| | | import com.ruoyi.sales.pojo.ShippingInfo; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @Schema(name = "ShippingInfoVo", description = "è¥é管ç--åè´§ä¿¡æ¯") |
| | | public class ShippingInfoVo { |
| | | |
| | | private ShippingInfo shippingInfo; |
| | | |
| | | @Schema(description = "å货产åå表") |
| | | private List<ShippingProductVo> shippingProductVoList; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.procurementrecord.bean.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Data |
| | | @Schema(name = "ShippingProductVo", description = "è¥é管ç--åè´§åºåºäº§åå表") |
| | | public class ShippingProductVo { |
| | | @Schema(description = "åºåºåid") |
| | | private Long id; |
| | | |
| | | @Schema(description = "产åè§æ ¼id") |
| | | private Long productModelId; |
| | | |
| | | @Schema(description = "产å大类") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "è§æ ¼åå·") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "åä½") |
| | | private String unit; |
| | | |
| | | @Schema(description = "åºåºåå·") |
| | | private String outboundBatches; |
| | | |
| | | @Schema(description = "åè´§åºåºæ°é") |
| | | private BigDecimal stockOutNum; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·") |
| | | private String batchNo; |
| | | |
| | | @Schema(description = "æªéè´§æ°") |
| | | private BigDecimal unQuantity; |
| | | |
| | | @Schema(description = "éè´§æ»æ°") |
| | | private BigDecimal totalReturnNum; |
| | | |
| | | @Schema(description = "å«ç¨åä»·") |
| | | private BigDecimal taxInclusiveUnitPrice; |
| | | } |
| | |
| | | package com.ruoyi.procurementrecord.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.*; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementExceptionRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementExceptionRecord; |
| | | import com.ruoyi.procurementrecord.service.ProcurementRecordService; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.*; |
| | | import com.ruoyi.procurementrecord.bean.dto.*; |
| | | import com.ruoyi.procurementrecord.mapper.CustomStorageMapper; |
| | | import com.ruoyi.procurementrecord.pojo.CustomStorage; |
| | | import com.ruoyi.procurementrecord.service.ProcurementRecordService; |
| | |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import lombok.AllArgsConstructor; |
| | | import org.apache.ibatis.annotations.Delete; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; |
| | | import com.ruoyi.procurementrecord.service.ProcurementRecordOutService; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnManagement; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingInfoVo; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.ruoyi.procurementrecord.service.ReturnManagementService; |
| | | import com.ruoyi.procurementrecord.service.ReturnSaleProductService; |
| | | import com.ruoyi.procurementrecord.service.impl.ReturnSaleProductServiceImpl; |
| | | import com.ruoyi.sales.dto.SalesLedgerDto; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | } |
| | | |
| | | @GetMapping("/getByShippingId") |
| | | @Operation(summary = "éå®éè´§-æ ¹æ®åºåºåæ¥è¯¢éå®è®¢å以å产åä¿¡æ¯") |
| | | @Operation(summary = "éå®éè´§-æ ¹æ®åè´§åæ¥è¯¢éå®è®¢å以ååºåºç产åä¿¡æ¯") |
| | | public AjaxResult getByShippingId(Long shippingId) { |
| | | SalesLedgerDto salesLedgerDto = returnManagementService.getReturnManagementDtoByShippingIdId(shippingId); |
| | | return success(salesLedgerDto); |
| | | ShippingInfoVo shippingInfoVo = returnManagementService.getReturnManagementDtoByShippingIdId(shippingId); |
| | | return success(shippingInfoVo); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementDto; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementPageDto; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.bean.dto.SalesReturnDto; |
| | | import com.ruoyi.account.bean.vo.SalesReturnVo; |
| | | import com.ruoyi.procurementrecord.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnManagement; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | |
| | | package com.ruoyi.procurementrecord.mapper; |
| | | |
| | | import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | @Schema(description = "å建æ¶é´") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | @Schema(description = "æ´æ°æ¶é´") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private LocalDateTime updateTime; |
| | | |
| | | @Schema(description = "åå»ºç¨æ·") |
| | |
| | | package com.ruoyi.procurementrecord.pojo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Schema(description = "éè´§åid") |
| | | private Long returnManagementId; |
| | | |
| | | @Schema(description = "é货产åid") |
| | | private Long returnsalesLedgerProductId; |
| | | @Schema(description = "å
³èåºåºåid") |
| | | private Long stockOutRecordId; |
| | | |
| | | @Schema(description = "éè´§äº§åæ°é") |
| | | private BigDecimal num; |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.*; |
| | | import com.ruoyi.procurementrecord.bean.dto.*; |
| | | import com.ruoyi.procurementrecord.pojo.CustomStorage; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.procurementrecord.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingInfoVo; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnManagement; |
| | | import com.ruoyi.sales.dto.SalesLedgerDto; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | |
| | | boolean updateReturnManagementDto(ReturnManagementDto returnManagementDto); |
| | | |
| | | SalesLedgerDto getReturnManagementDtoByShippingIdId(Long shippingId); |
| | | ShippingInfoVo getReturnManagementDtoByShippingIdId(Long shippingId); |
| | | |
| | | boolean handle(Long returnManagementId); |
| | | |
| | |
| | | package com.ruoyi.procurementrecord.service; |
| | | |
| | | import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutAdd; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ProcurementUpdateDto; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; |
| | | import com.ruoyi.procurementrecord.service.ProcurementRecordOutService; |
| | |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.procurementrecord.dto.*; |
| | | import com.ruoyi.procurementrecord.bean.dto.*; |
| | | import com.ruoyi.procurementrecord.mapper.CustomStorageMapper; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; |
| | |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.procurementrecord.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingInfoVo; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingProductVo; |
| | | import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnManagement; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.ruoyi.procurementrecord.service.ReturnManagementService; |
| | | import com.ruoyi.procurementrecord.service.ReturnSaleProductService; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.sales.dto.SalesLedgerDto; |
| | | import com.ruoyi.sales.dto.SalesLedgerProductDto; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import com.ruoyi.sales.pojo.ShippingInfo; |
| | | import com.ruoyi.sales.service.ShippingInfoService; |
| | | import lombok.RequiredArgsConstructor; |
| | |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | |
| | | |
| | | @Override |
| | | public boolean updateReturnManagementDto(ReturnManagementDto returnManagementDto) { |
| | | List<ReturnSaleProduct> returnSaleProducts = new ArrayList<>(); |
| | | if (!CollectionUtils.isEmpty(returnManagementDto.getReturnSaleProducts())) { |
| | | returnManagementDto.getReturnSaleProducts().stream().forEach(returnSaleProductDto -> { |
| | | ReturnSaleProduct returnSaleProduct = new ReturnSaleProduct(); |
| | | BeanUtils.copyProperties(returnSaleProductDto, returnSaleProduct); |
| | | returnSaleProducts.add(returnSaleProduct); |
| | | if (returnSaleProductDto.getId() == null){ |
| | | returnSaleProduct.setReturnManagementId(returnManagementDto.getId()); |
| | | returnSaleProduct.setStatus(0); |
| | | returnSaleProductService.save(returnSaleProduct); |
| | | }else returnSaleProductService.updateById(returnSaleProduct); |
| | | }); |
| | | } |
| | | returnSaleProductService.updateBatchById(returnSaleProducts); |
| | | return updateById(returnManagementDto); |
| | | } |
| | | |
| | | @Override |
| | | public SalesLedgerDto getReturnManagementDtoByShippingIdId(Long shippingId) { |
| | | public ShippingInfoVo getReturnManagementDtoByShippingIdId(Long shippingId) { |
| | | ShippingInfo byId = shippingInfoService.getById(shippingId); |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(byId.getSalesLedgerId()); |
| | | SalesLedgerDto salesLedgerDto = new SalesLedgerDto(); |
| | | BeanUtils.copyProperties(salesLedger, salesLedgerDto); |
| | | |
| | | List<SalesLedgerProductDto> salesLedgerProductDtos = shippingInfoService.getReturnManagementDtoById(byId.getId()); |
| | | salesLedgerDto.setProductDtoData(salesLedgerProductDtos); |
| | | return salesLedgerDto; |
| | | ShippingInfoVo shippingInfoVo = new ShippingInfoVo(); |
| | | shippingInfoVo.setShippingInfo(byId); |
| | | List<ShippingProductVo> shippingProductVos = shippingInfoService.getReturnManagementDtoById(byId.getId()); |
| | | shippingInfoVo.setShippingProductVoList(shippingProductVos); |
| | | return shippingInfoVo; |
| | | } |
| | | |
| | | @Override |
| | |
| | | ReturnManagement byId = this.getById(returnManagementId); |
| | | List<ReturnSaleProductDto> list = returnSaleProductService.listReturnSaleProduct(returnManagementId); |
| | | byId.setStatus(1); |
| | | byId.setSettler(SecurityUtils.getLoginUser().getNickName()); |
| | | updateById(byId); |
| | | SalesRefundAmountOrderDto salesRefundAmountOrder = new SalesRefundAmountOrderDto(); |
| | | salesRefundAmountOrder.setReturnManagementId(returnManagementId); |
| | |
| | | salesRefundAmountOrder.setRefundedAmount(new BigDecimal(0)); |
| | | // æ¯å¦æè´¨éé®é¢ |
| | | if (returnSaleProduct.getIsQuality() == 1) { |
| | | // æè´¨éé®é¢ï¼å
¥ä¸åæ ¼åº |
| | | stockUtils.addUnStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_UNSTOCK_IN.getCode(),returnSaleProduct.getId()); |
| | | // æè´¨éé®é¢ï¼å
¥ä¸åæ ¼åº(å¸¦æ¹æ¬¡) |
| | | stockUtils.addUnStockWithBatchNo(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_UNSTOCK_IN.getCode(),returnSaleProduct.getId(),returnSaleProduct.getBatchNo()); |
| | | }else{ |
| | | // æ è´¨éé®é¢ï¼å
¥åæ ¼åº |
| | | stockUtils.addStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_HE_IN.getCode(),returnSaleProduct.getId()); |
| | | // æ è´¨éé®é¢ï¼å
¥åæ ¼åº(å¸¦æ¹æ¬¡) |
| | | stockUtils.addStockWithBatchNo(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_HE_IN.getCode(),returnSaleProduct.getId(),returnSaleProduct.getBatchNo()); |
| | | } |
| | | } |
| | | salesRefundAmountOrder.setRefundAmount(bigDecimal); |
| | |
| | | package com.ruoyi.procurementrecord.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto; |
| | | import com.ruoyi.procurementrecord.mapper.ReturnSaleProductMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct; |
| | | import com.ruoyi.procurementrecord.service.ReturnSaleProductService; |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.ruoyi.common.enums.ReviewStatusEnum; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.dto.StockUninventoryDto; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.pojo.StockOutRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | |
| | | private final StockInventoryService stockInventoryService; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockOutRecordService stockOutRecordService; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | |
| | | /** |
| | | * ä¸åæ ¼å
¥åº |
| | |
| | | stockUninventoryDto.setRecordType(String.valueOf(recordType)); |
| | | stockUninventoryDto.setQualitity(quantity); |
| | | stockUninventoryDto.setProductModelId(productModelId); |
| | | stockUninventoryService.addStockInRecordOnly(stockUninventoryDto); |
| | | } |
| | | |
| | | /** |
| | | * ä¸åæ ¼å
¥åºå¸¦æ¹æ¬¡å· |
| | | * |
| | | * @param productModelId |
| | | * @param quantity |
| | | * @param recordType |
| | | * @param recordId |
| | | */ |
| | | public void addUnStockWithBatchNo(Long productModelId, BigDecimal quantity, String recordType, Long recordId, String batchNo) { |
| | | StockUninventoryDto stockUninventoryDto = new StockUninventoryDto(); |
| | | stockUninventoryDto.setRecordId(recordId); |
| | | stockUninventoryDto.setRecordType(String.valueOf(recordType)); |
| | | stockUninventoryDto.setQualitity(quantity); |
| | | stockUninventoryDto.setProductModelId(productModelId); |
| | | stockUninventoryDto.setBatchNo(batchNo); |
| | | stockUninventoryService.addStockInRecordOnly(stockUninventoryDto); |
| | | } |
| | | |
| | |
| | | public void shipmentStatus(String recordType, Long recordId) { |
| | | LambdaQueryWrapper<StockOutRecord> queryWrapper = new LambdaQueryWrapper<StockOutRecord>().eq(StockOutRecord::getRecordType, recordType) |
| | | .eq(StockOutRecord::getRecordId, recordId); |
| | | StockOutRecord stockOutRecord = stockOutRecordService.getOne(queryWrapper); |
| | | stockOutRecord.setApprovalStatus(0); |
| | | stockOutRecordService.updateById(stockOutRecord); |
| | | stockOutRecordService.list(queryWrapper).stream().forEach(stockOutRecord -> { |
| | | stockOutRecord.setApprovalStatus(0); |
| | | stockOutRecordService.updateById(stockOutRecord); |
| | | }); |
| | | } |
| | | |
| | | //ä¸åæ ¼åºåå é¤ |
| | | public void deleteStockInRecord(Long recordId, String recordType) { |
| | | StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>() |
| | | .lambda().eq(StockInRecord::getRecordId, recordId) |
| | | .eq(StockInRecord::getRecordType, recordType)); |
| | | .eq(StockInRecord::getRecordType, recordType), false); |
| | | if (ObjectUtils.isNotEmpty(one)) { |
| | | stockInRecordService.batchDelete(Collections.singletonList(one.getId())); |
| | | //å°åºåå忥 |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordId(recordId); |
| | | stockInventoryDto.setRecordType(recordType); |
| | | stockInventoryDto.setQualitity(one.getStockInNum()); |
| | | stockInventoryMapper.updateSubtractStockInventory((stockInventoryDto)); |
| | | if (ReviewStatusEnum.APPROVED.getCode().equals(one.getApprovalStatus())) { |
| | | stockInRecordService.batchDelete(Collections.singletonList(one.getId())); |
| | | } else { |
| | | stockInRecordService.removeById(one.getId()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | //å é¤åºåºè®°å½ |
| | | public void deleteStockOutRecord(Long recordId, String recordType) { |
| | | StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>() |
| | | .lambda().eq(StockOutRecord::getRecordId, recordId) |
| | | .eq(StockOutRecord::getRecordType, recordType)); |
| | | .eq(StockOutRecord::getRecordType, recordType), false); |
| | | if (ObjectUtils.isNotEmpty(one)) { |
| | | stockOutRecordService.batchDelete(Collections.singletonList(one.getId())); |
| | | //å°åºåå 忥 |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setRecordId(recordId); |
| | | stockInventoryDto.setRecordType(recordType); |
| | | stockInventoryDto.setQualitity(one.getStockOutNum()); |
| | | stockInventoryMapper.updateAddStockInventory((stockInventoryDto)); |
| | | if (ReviewStatusEnum.APPROVED.getCode().equals(one.getApprovalStatus())) { |
| | | stockOutRecordService.batchDelete(Collections.singletonList(one.getId())); |
| | | } else { |
| | | stockOutRecordService.removeById(one.getId()); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @Schema(description = "éå®å°è´¦id") |
| | | private Long salesLedgerId; |
| | | |
| | | @Schema(description = "éå®äº§åè§æ ¼id") |
| | | private Long salesLedgerProductId; |
| | | |
| | | @Schema(description = "æ¥å·¥è¡¨id") |
| | | private Long productionProductMainId; |
| | | |
| | |
| | | @TableId(type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @Schema(description = "æ¥å·¥id") |
| | | private Long productMainId; |
| | | |
| | | @Schema(description = "ç产æ¥å·¥ä¸»è¡¨id") |
| | | private Long productionProductMainId; |
| | | |
| | |
| | | @TableId(type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | | @Schema(description = "æ¥å·¥id") |
| | | private Long productMainId; |
| | | |
| | | @Schema(description = "ç产æ¥å·¥ä¸»è¡¨id") |
| | | private Long productionProductMainId; |
| | | |
| | |
| | | package com.ruoyi.production.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.production.bean.dto.ProductionBomStructureDto; |
| | | import com.ruoyi.production.bean.vo.ProductionBomStructureVo; |
| | | import com.ruoyi.production.mapper.ProductionBomStructureMapper; |
| | | import com.ruoyi.production.mapper.ProductionOperationTaskMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderBomMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper; |
| | | import com.ruoyi.production.mapper.ProductionProductMainMapper; |
| | | import com.ruoyi.production.pojo.ProductionBomStructure; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionOrderBom; |
| | | import com.ruoyi.production.pojo.ProductionOrderRouting; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam; |
| | | import com.ruoyi.production.pojo.ProductionProductMain; |
| | | import com.ruoyi.production.service.ProductionBomStructureService; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationParamMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyParamMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyOperation; |
| | | import com.ruoyi.technology.pojo.TechnologyOperationParam; |
| | | import com.ruoyi.technology.pojo.TechnologyParam; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @RequiredArgsConstructor() |
| | | public class ProductionBomStructureServiceImpl extends ServiceImpl<ProductionBomStructureMapper, ProductionBomStructure> implements ProductionBomStructureService { |
| | | |
| | | private final ProductionBomStructureMapper productionBomStructureMapper; |
| | | private final ProductionBomStructureMapper productionBomStructureMapper; |
| | | private final ProductionOrderBomMapper productionOrderBomMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | private final ProductionOrderRoutingMapper productionOrderRoutingMapper; |
| | | private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; |
| | | private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final TechnologyOperationParamMapper technologyOperationParamMapper; |
| | | private final TechnologyParamMapper technologyParamMapper; |
| | | |
| | | /** |
| | | * æ ¹æ®BOMæ¥è¯¢å¹¶ç»è£
ç»ææ ã |
| | |
| | | if (!updateList.isEmpty()) { |
| | | this.updateBatchById(updateList); |
| | | } |
| | | syncDemandedQuantityAndTaskPlanQuantity(orderBomId, dto.getProductionOrderId()); |
| | | return true; |
| | | } |
| | | |
| | | private void syncDemandedQuantityAndTaskPlanQuantity(Long orderBomId, Long productionOrderId) { |
| | | if (orderBomId == null) { |
| | | return; |
| | | } |
| | | ProductionOrderBom orderBom = productionOrderBomMapper.selectById(orderBomId); |
| | | if (orderBom == null) { |
| | | return; |
| | | } |
| | | Long currentProductionOrderId = productionOrderId != null ? productionOrderId : orderBom.getProductionOrderId(); |
| | | if (currentProductionOrderId == null) { |
| | | return; |
| | | } |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(currentProductionOrderId); |
| | | if (productionOrder == null) { |
| | | return; |
| | | } |
| | | |
| | | BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity()); |
| | | List<ProductionBomStructure> structureList = this.list( |
| | | Wrappers.<ProductionBomStructure>lambdaQuery() |
| | | .eq(ProductionBomStructure::getProductionOrderBomId, orderBomId) |
| | | .orderByAsc(ProductionBomStructure::getId)); |
| | | //忥鿱æ°é |
| | | syncStructureDemandedQuantity(structureList, orderQuantity); |
| | | Long rootProductModelId = orderBom.getProductModelId() != null ? orderBom.getProductModelId() : productionOrder.getProductModelId(); |
| | | //忥ç产工èºè·¯çº¿ |
| | | syncRoutingOperationsByBom(currentProductionOrderId, productionOrder, orderBom, structureList, rootProductModelId); |
| | | //忥工å |
| | | syncTaskPlanQuantity( |
| | | currentProductionOrderId, |
| | | structureList, |
| | | orderQuantity, |
| | | rootProductModelId); |
| | | } |
| | | |
| | | private void syncStructureDemandedQuantity(List<ProductionBomStructure> structureList, BigDecimal orderQuantity) { |
| | | if (structureList == null || structureList.isEmpty()) { |
| | | return; |
| | | } |
| | | List<ProductionBomStructure> updateList = new ArrayList<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | for (ProductionBomStructure structure : structureList) { |
| | | if (structure == null || structure.getId() == null) { |
| | | continue; |
| | | } |
| | | |
| | | BigDecimal demandedQuantity = lastProcessDemandedQuantity.multiply(defaultDecimal(structure.getUnitQuantity())); |
| | | // if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) { |
| | | // continue; |
| | | // } |
| | | ProductionBomStructure update = new ProductionBomStructure(); |
| | | update.setId(structure.getId()); |
| | | update.setDemandedQuantity(demandedQuantity); |
| | | updateList.add(update); |
| | | structure.setDemandedQuantity(demandedQuantity); |
| | | lastProcessDemandedQuantity = demandedQuantity; |
| | | } |
| | | if (!updateList.isEmpty()) { |
| | | this.updateBatchById(updateList); |
| | | } |
| | | } |
| | | |
| | | private void syncTaskPlanQuantity(Long productionOrderId, |
| | | List<ProductionBomStructure> structureList, |
| | | BigDecimal orderQuantity, |
| | | Long rootProductModelId) { |
| | | List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .eq(ProductionOperationTask::getProductionOrderId, productionOrderId) |
| | | .orderByAsc(ProductionOperationTask::getId)); |
| | | if (taskList == null || taskList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> routingOperationIds = taskList.stream() |
| | | .map(ProductionOperationTask::getProductionOrderRoutingOperationId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | if (routingOperationIds.isEmpty()) { |
| | | return; |
| | | } |
| | | Map<Long, ProductionOrderRoutingOperation> routingOperationMap = productionOrderRoutingOperationMapper |
| | | .selectBatchIds(routingOperationIds) |
| | | .stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionOrderRoutingOperation::getId, item -> item, (left, right) -> left)); |
| | | // Keep task plan quantities aligned with the same order BOM snapshot demand used during snapshot creation. |
| | | Map<String, BigDecimal> demandedQuantityMap = buildOperationDemandedQuantityMap(structureList, rootProductModelId); |
| | | for (ProductionOperationTask task : taskList) { |
| | | if (task == null || task.getId() == null || task.getProductionOrderRoutingOperationId() == null) { |
| | | continue; |
| | | } |
| | | ProductionOrderRoutingOperation routingOperation = routingOperationMap.get(task.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation == null) { |
| | | continue; |
| | | } |
| | | BigDecimal planQuantity = resolveTaskPlanQuantity( |
| | | routingOperation, |
| | | demandedQuantityMap, |
| | | orderQuantity, |
| | | rootProductModelId); |
| | | if (compareDecimal(task.getPlanQuantity(), planQuantity) == 0) { |
| | | continue; |
| | | } |
| | | ProductionOperationTask update = new ProductionOperationTask(); |
| | | update.setId(task.getId()); |
| | | update.setPlanQuantity(planQuantity); |
| | | productionOperationTaskMapper.updateById(update); |
| | | } |
| | | } |
| | | |
| | | private void syncRoutingOperationsByBom(Long productionOrderId, |
| | | ProductionOrder productionOrder, |
| | | ProductionOrderBom orderBom, |
| | | List<ProductionBomStructure> structureList, |
| | | Long rootProductModelId) { |
| | | ProductionOrderRouting orderRouting = getOrCreateOrderRoutingSnapshot(productionOrderId, productionOrder, orderBom, rootProductModelId); |
| | | List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(structureList, rootProductModelId); |
| | | List<ProductionOrderRoutingOperation> existingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperation::getOrderRoutingId, orderRouting.getId()) |
| | | .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId) |
| | | .orderByAsc(ProductionOrderRoutingOperation::getDragSort) |
| | | .orderByAsc(ProductionOrderRoutingOperation::getId)); |
| | | Map<String, Deque<ProductionOrderRoutingOperation>> existingBucketMap = buildExistingRoutingOperationBucketMap(existingOperationList); |
| | | List<ProductionOrderRoutingOperation> finalOperationList = new ArrayList<>(); |
| | | for (ProductionOrderRoutingOperation desiredOperation : desiredOperationList) { |
| | | String bucketKey = buildRoutingOperationBucketKey( |
| | | desiredOperation.getTechnologyOperationId(), |
| | | desiredOperation.getProductModelId()); |
| | | Deque<ProductionOrderRoutingOperation> matchedQueue = existingBucketMap.get(bucketKey); |
| | | ProductionOrderRoutingOperation matchedOperation = matchedQueue == null ? null : matchedQueue.pollFirst(); |
| | | if (matchedOperation == null) { |
| | | matchedOperation = insertRoutingOperationSnapshot(orderRouting.getId(), productionOrderId, desiredOperation); |
| | | } else { |
| | | updateRoutingOperationSnapshotIfNecessary(desiredOperation, orderRouting.getId(), productionOrderId, matchedOperation); |
| | | } |
| | | finalOperationList.add(matchedOperation); |
| | | } |
| | | for (Deque<ProductionOrderRoutingOperation> queue : existingBucketMap.values()) { |
| | | while (queue != null && !queue.isEmpty()) { |
| | | removeRoutingOperationSnapshot(queue.pollFirst()); |
| | | } |
| | | } |
| | | syncRoutingOperationTasks(productionOrderId, finalOperationList); |
| | | } |
| | | |
| | | private ProductionOrderRouting getOrCreateOrderRoutingSnapshot(Long productionOrderId, |
| | | ProductionOrder productionOrder, |
| | | ProductionOrderBom orderBom, |
| | | Long rootProductModelId) { |
| | | ProductionOrderRouting orderRouting = productionOrderRoutingMapper.selectOne( |
| | | Wrappers.<ProductionOrderRouting>lambdaQuery() |
| | | .eq(ProductionOrderRouting::getProductionOrderId, productionOrderId) |
| | | .orderByDesc(ProductionOrderRouting::getId) |
| | | .last("limit 1")); |
| | | if (orderRouting == null) { |
| | | orderRouting = new ProductionOrderRouting(); |
| | | orderRouting.setProductionOrderId(productionOrderId); |
| | | orderRouting.setProductModelId(rootProductModelId); |
| | | orderRouting.setTechnologyRoutingId(productionOrder == null ? null : productionOrder.getTechnologyRoutingId()); |
| | | orderRouting.setBomId(orderBom == null ? null : orderBom.getBomId()); |
| | | orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId()); |
| | | productionOrderRoutingMapper.insert(orderRouting); |
| | | return orderRouting; |
| | | } |
| | | ProductionOrderRouting update = new ProductionOrderRouting(); |
| | | update.setId(orderRouting.getId()); |
| | | boolean changed = false; |
| | | if (!Objects.equals(orderRouting.getProductModelId(), rootProductModelId)) { |
| | | update.setProductModelId(rootProductModelId); |
| | | orderRouting.setProductModelId(rootProductModelId); |
| | | changed = true; |
| | | } |
| | | Long technologyRoutingId = productionOrder == null ? null : productionOrder.getTechnologyRoutingId(); |
| | | if (!Objects.equals(orderRouting.getTechnologyRoutingId(), technologyRoutingId)) { |
| | | update.setTechnologyRoutingId(technologyRoutingId); |
| | | orderRouting.setTechnologyRoutingId(technologyRoutingId); |
| | | changed = true; |
| | | } |
| | | Long bomId = orderBom == null ? null : orderBom.getBomId(); |
| | | if (!Objects.equals(orderRouting.getBomId(), bomId)) { |
| | | update.setBomId(bomId); |
| | | orderRouting.setBomId(bomId); |
| | | changed = true; |
| | | } |
| | | Long orderBomId = orderBom == null ? null : orderBom.getId(); |
| | | if (!Objects.equals(orderRouting.getOrderBomId(), orderBomId)) { |
| | | update.setOrderBomId(orderBomId); |
| | | orderRouting.setOrderBomId(orderBomId); |
| | | changed = true; |
| | | } |
| | | if (changed) { |
| | | productionOrderRoutingMapper.updateById(update); |
| | | } |
| | | return orderRouting; |
| | | } |
| | | |
| | | private List<ProductionOrderRoutingOperation> buildDesiredRoutingOperationList(List<ProductionBomStructure> structureList, |
| | | Long rootProductModelId) { |
| | | if (structureList == null || structureList.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | Map<Long, ProductionBomStructure> structureById = structureList.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); |
| | | Map<String, ProductionBomStructure> uniqueOperationMap = new LinkedHashMap<>(); |
| | | for (ProductionBomStructure bomStructure : structureList) { |
| | | if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) { |
| | | continue; |
| | | } |
| | | Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId); |
| | | uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure); |
| | | } |
| | | List<ProductionOrderRoutingOperation> desiredOperationList = new ArrayList<>(); |
| | | int dragSort = 1; |
| | | for (ProductionBomStructure bomStructure : uniqueOperationMap.values()) { |
| | | Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId); |
| | | TechnologyOperation technologyOperation = getTechnologyOperation(bomStructure.getTechnologyOperationId()); |
| | | ProductionOrderRoutingOperation routingOperation = new ProductionOrderRoutingOperation(); |
| | | routingOperation.setProductModelId(outputProductModelId); |
| | | routingOperation.setTechnologyOperationId(bomStructure.getTechnologyOperationId()); |
| | | routingOperation.setOperationName(technologyOperation == null ? null : technologyOperation.getName()); |
| | | routingOperation.setIsQuality(technologyOperation == null ? null : technologyOperation.getIsQuality()); |
| | | routingOperation.setIsProduction(technologyOperation == null ? null : technologyOperation.getIsProduction()); |
| | | routingOperation.setType(technologyOperation == null ? null : technologyOperation.getType()); |
| | | routingOperation.setDragSort(dragSort++); |
| | | desiredOperationList.add(routingOperation); |
| | | } |
| | | return desiredOperationList; |
| | | } |
| | | |
| | | private Map<String, Deque<ProductionOrderRoutingOperation>> buildExistingRoutingOperationBucketMap(List<ProductionOrderRoutingOperation> existingOperationList) { |
| | | Map<String, Deque<ProductionOrderRoutingOperation>> existingBucketMap = new LinkedHashMap<>(); |
| | | if (existingOperationList == null || existingOperationList.isEmpty()) { |
| | | return existingBucketMap; |
| | | } |
| | | for (ProductionOrderRoutingOperation routingOperation : existingOperationList) { |
| | | String bucketKey = buildRoutingOperationBucketKey( |
| | | routingOperation.getTechnologyOperationId(), |
| | | routingOperation.getProductModelId()); |
| | | existingBucketMap.computeIfAbsent(bucketKey, key -> new ArrayDeque<>()).addLast(routingOperation); |
| | | } |
| | | return existingBucketMap; |
| | | } |
| | | |
| | | private ProductionOrderRoutingOperation insertRoutingOperationSnapshot(Long orderRoutingId, |
| | | Long productionOrderId, |
| | | ProductionOrderRoutingOperation desiredOperation) { |
| | | ProductionOrderRoutingOperation insert = new ProductionOrderRoutingOperation(); |
| | | insert.setOrderRoutingId(orderRoutingId); |
| | | insert.setProductionOrderId(productionOrderId); |
| | | insert.setProductModelId(desiredOperation.getProductModelId()); |
| | | insert.setTechnologyOperationId(desiredOperation.getTechnologyOperationId()); |
| | | insert.setOperationName(desiredOperation.getOperationName()); |
| | | insert.setIsQuality(desiredOperation.getIsQuality()); |
| | | insert.setIsProduction(desiredOperation.getIsProduction()); |
| | | insert.setType(desiredOperation.getType()); |
| | | insert.setDragSort(desiredOperation.getDragSort()); |
| | | productionOrderRoutingOperationMapper.insert(insert); |
| | | syncRoutingOperationParams(insert.getId(), productionOrderId, insert.getTechnologyOperationId()); |
| | | return insert; |
| | | } |
| | | |
| | | private void updateRoutingOperationSnapshotIfNecessary(ProductionOrderRoutingOperation currentOperation, |
| | | Long orderRoutingId, |
| | | Long productionOrderId, |
| | | ProductionOrderRoutingOperation desiredOperation) { |
| | | if (currentOperation == null || currentOperation.getId() == null) { |
| | | return; |
| | | } |
| | | ProductionOrderRoutingOperation update = new ProductionOrderRoutingOperation(); |
| | | update.setId(currentOperation.getId()); |
| | | boolean changed = false; |
| | | if (!Objects.equals(currentOperation.getOrderRoutingId(), orderRoutingId)) { |
| | | update.setOrderRoutingId(orderRoutingId); |
| | | currentOperation.setOrderRoutingId(orderRoutingId); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getProductionOrderId(), productionOrderId)) { |
| | | update.setProductionOrderId(productionOrderId); |
| | | currentOperation.setProductionOrderId(productionOrderId); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getProductModelId(), desiredOperation.getProductModelId())) { |
| | | update.setProductModelId(desiredOperation.getProductModelId()); |
| | | currentOperation.setProductModelId(desiredOperation.getProductModelId()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getTechnologyOperationId(), desiredOperation.getTechnologyOperationId())) { |
| | | update.setTechnologyOperationId(desiredOperation.getTechnologyOperationId()); |
| | | currentOperation.setTechnologyOperationId(desiredOperation.getTechnologyOperationId()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getOperationName(), desiredOperation.getOperationName())) { |
| | | update.setOperationName(desiredOperation.getOperationName()); |
| | | currentOperation.setOperationName(desiredOperation.getOperationName()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getIsQuality(), desiredOperation.getIsQuality())) { |
| | | update.setIsQuality(desiredOperation.getIsQuality()); |
| | | currentOperation.setIsQuality(desiredOperation.getIsQuality()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getIsProduction(), desiredOperation.getIsProduction())) { |
| | | update.setIsProduction(desiredOperation.getIsProduction()); |
| | | currentOperation.setIsProduction(desiredOperation.getIsProduction()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getType(), desiredOperation.getType())) { |
| | | update.setType(desiredOperation.getType()); |
| | | currentOperation.setType(desiredOperation.getType()); |
| | | changed = true; |
| | | } |
| | | if (!Objects.equals(currentOperation.getDragSort(), desiredOperation.getDragSort())) { |
| | | update.setDragSort(desiredOperation.getDragSort()); |
| | | currentOperation.setDragSort(desiredOperation.getDragSort()); |
| | | changed = true; |
| | | } |
| | | if (changed) { |
| | | productionOrderRoutingOperationMapper.updateById(update); |
| | | } |
| | | } |
| | | |
| | | private void removeRoutingOperationSnapshot(ProductionOrderRoutingOperation routingOperation) { |
| | | if (routingOperation == null || routingOperation.getId() == null) { |
| | | return; |
| | | } |
| | | ProductionOperationTask task = productionOperationTaskMapper.selectOne( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, routingOperation.getId()) |
| | | .last("limit 1")); |
| | | if (task != null) { |
| | | validateTaskCanRemove(task); |
| | | productionOperationTaskMapper.deleteById(task.getId()); |
| | | } |
| | | productionOrderRoutingOperationParamMapper.delete( |
| | | Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery() |
| | | .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperation.getId())); |
| | | productionOrderRoutingOperationMapper.deleteById(routingOperation.getId()); |
| | | } |
| | | |
| | | private void syncRoutingOperationTasks(Long productionOrderId, List<ProductionOrderRoutingOperation> routingOperationList) { |
| | | if (routingOperationList == null || routingOperationList.isEmpty()) { |
| | | return; |
| | | } |
| | | List<Long> routingOperationIdList = routingOperationList.stream() |
| | | .map(ProductionOrderRoutingOperation::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (routingOperationIdList.isEmpty()) { |
| | | return; |
| | | } |
| | | Map<Long, ProductionOperationTask> taskByRoutingOperationId = productionOperationTaskMapper.selectList( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .in(ProductionOperationTask::getProductionOrderRoutingOperationId, routingOperationIdList) |
| | | .orderByAsc(ProductionOperationTask::getId)) |
| | | .stream() |
| | | .filter(item -> item != null && item.getProductionOrderRoutingOperationId() != null) |
| | | .collect(Collectors.toMap( |
| | | ProductionOperationTask::getProductionOrderRoutingOperationId, |
| | | item -> item, |
| | | (left, right) -> left, |
| | | LinkedHashMap::new)); |
| | | for (int i = 0; i < routingOperationList.size(); i++) { |
| | | ProductionOrderRoutingOperation routingOperation = routingOperationList.get(i); |
| | | if (routingOperation == null || routingOperation.getId() == null) { |
| | | continue; |
| | | } |
| | | boolean shouldHaveTask = i == routingOperationList.size() - 1 || Boolean.TRUE.equals(routingOperation.getIsProduction()); |
| | | ProductionOperationTask existingTask = taskByRoutingOperationId.get(routingOperation.getId()); |
| | | if (shouldHaveTask) { |
| | | if (existingTask == null) { |
| | | ProductionOperationTask task = new ProductionOperationTask(); |
| | | task.setProductionOrderId(productionOrderId); |
| | | task.setProductionOrderRoutingOperationId(routingOperation.getId()); |
| | | task.setPlanQuantity(BigDecimal.ZERO); |
| | | task.setCompleteQuantity(BigDecimal.ZERO); |
| | | task.setWorkOrderNo(generateNextTaskNo()); |
| | | task.setStatus(2); |
| | | productionOperationTaskMapper.insert(task); |
| | | } |
| | | continue; |
| | | } |
| | | if (existingTask != null) { |
| | | validateTaskCanRemove(existingTask); |
| | | productionOperationTaskMapper.deleteById(existingTask.getId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void validateTaskCanRemove(ProductionOperationTask task) { |
| | | if (task == null || task.getId() == null) { |
| | | return; |
| | | } |
| | | if (defaultDecimal(task.getCompleteQuantity()).compareTo(BigDecimal.ZERO) > 0) { |
| | | throw new ServiceException("å·¥åºå·²äº§çæ¥å·¥è®°å½ï¼æ æ³æ ¹æ® BOM åæ´å é¤å¯¹åºå·¥åºå¿«ç
§"); |
| | | } |
| | | long reportCount = productionProductMainMapper.selectCount( |
| | | Wrappers.<ProductionProductMain>lambdaQuery() |
| | | .eq(ProductionProductMain::getProductionOperationTaskId, task.getId())); |
| | | if (reportCount > 0) { |
| | | throw new ServiceException("å·¥åºå·²äº§çæ¥å·¥è®°å½ï¼æ æ³æ ¹æ® BOM åæ´å é¤å¯¹åºå·¥å"); |
| | | } |
| | | } |
| | | |
| | | private void syncRoutingOperationParams(Long routingOperationId, Long productionOrderId, Long technologyOperationId) { |
| | | if (routingOperationId == null || technologyOperationId == null) { |
| | | return; |
| | | } |
| | | List<TechnologyOperationParam> operationParamList = technologyOperationParamMapper.selectList( |
| | | Wrappers.<TechnologyOperationParam>lambdaQuery() |
| | | .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationId) |
| | | .orderByAsc(TechnologyOperationParam::getId)); |
| | | for (TechnologyOperationParam operationParam : operationParamList) { |
| | | TechnologyParam technologyParam = technologyParamMapper.selectById(operationParam.getTechnologyParamId()); |
| | | if (technologyParam == null) { |
| | | continue; |
| | | } |
| | | ProductionOrderRoutingOperationParam snapshot = new ProductionOrderRoutingOperationParam(); |
| | | snapshot.setProductionOrderId(productionOrderId); |
| | | snapshot.setProductionOrderRoutingOperationId(routingOperationId); |
| | | snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId()); |
| | | snapshot.setTechnologyOperationParamId(operationParam.getId()); |
| | | snapshot.setParamId(technologyParam.getId()); |
| | | snapshot.setParamCode(technologyParam.getParamCode()); |
| | | snapshot.setParamName(technologyParam.getParamName()); |
| | | snapshot.setParamType(technologyParam.getParamType()); |
| | | snapshot.setParamFormat(technologyParam.getParamFormat()); |
| | | snapshot.setUnit(technologyParam.getUnit()); |
| | | snapshot.setIsRequired(technologyParam.getIsRequired()); |
| | | snapshot.setRemark(technologyParam.getRemark()); |
| | | snapshot.setStandardValue(operationParam.getStandardValue()); |
| | | productionOrderRoutingOperationParamMapper.insert(snapshot); |
| | | } |
| | | } |
| | | |
| | | private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> structureList, |
| | | Long rootProductModelId) { |
| | | if (structureList == null || structureList.isEmpty()) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | Map<Long, ProductionBomStructure> structureById = structureList.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); |
| | | Map<String, BigDecimal> demandedQuantityMap = new HashMap<>(); |
| | | Set<String> mergedOutputNodeKeySet = new HashSet<>(); |
| | | for (ProductionBomStructure bomStructure : structureList) { |
| | | if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) { |
| | | continue; |
| | | } |
| | | // Resolve the output node first, then read the output node demand for the task plan quantity. |
| | | ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById); |
| | | Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId); |
| | | if (outputProductModelId == null) { |
| | | continue; |
| | | } |
| | | String mergedOutputNodeKey = buildOperationOutputNodeKey( |
| | | bomStructure.getTechnologyOperationId(), |
| | | outputNode == null ? null : outputNode.getId(), |
| | | outputProductModelId); |
| | | if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) { |
| | | continue; |
| | | } |
| | | // Multiple input rows can point to the same output node, so only count that output demand once. |
| | | String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId); |
| | | demandedQuantityMap.merge(key, defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()), BigDecimal::add); |
| | | } |
| | | return demandedQuantityMap; |
| | | } |
| | | |
| | | private BigDecimal resolveTaskPlanQuantity(ProductionOrderRoutingOperation routingOperation, |
| | | Map<String, BigDecimal> demandedQuantityMap, |
| | | BigDecimal orderQuantity, |
| | | Long rootProductModelId) { |
| | | if (routingOperation == null || demandedQuantityMap == null || demandedQuantityMap.isEmpty()) { |
| | | return orderQuantity; |
| | | } |
| | | Long outputProductModelId = routingOperation.getProductModelId() != null |
| | | ? routingOperation.getProductModelId() |
| | | : rootProductModelId; |
| | | String key = buildOperationDemandedQuantityKey( |
| | | routingOperation.getTechnologyOperationId(), |
| | | outputProductModelId); |
| | | BigDecimal planQuantity = demandedQuantityMap.get(key); |
| | | return planQuantity != null ? planQuantity : orderQuantity; |
| | | } |
| | | |
| | | private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) { |
| | | return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId); |
| | | } |
| | | |
| | | private String buildRoutingOperationBucketKey(Long operationId, Long outputProductModelId) { |
| | | return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId); |
| | | } |
| | | |
| | | private String buildBomOperationDedupKey(ProductionBomStructure bomStructure, Long outputProductModelId) { |
| | | Long operationId = bomStructure == null ? null : bomStructure.getTechnologyOperationId(); |
| | | Long parentId = bomStructure == null ? null : bomStructure.getParentId(); |
| | | return operationId + "#" + outputProductModelId + "#" + parentId; |
| | | } |
| | | |
| | | private String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) { |
| | | return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId); |
| | | } |
| | | |
| | | private ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure, |
| | | Map<Long, ProductionBomStructure> structureById) { |
| | | if (bomStructure == null) { |
| | | return null; |
| | | } |
| | | // The root node is the first output node; other rows use their direct parent as the current operation output. |
| | | if (bomStructure.getParentId() == null) { |
| | | return bomStructure; |
| | | } |
| | | ProductionBomStructure parent = structureById.get(bomStructure.getParentId()); |
| | | return parent != null ? parent : bomStructure; |
| | | } |
| | | |
| | | private Long resolveOutputProductModelId(ProductionBomStructure outputNode, |
| | | Long rootProductModelId) { |
| | | if (outputNode == null) { |
| | | return rootProductModelId; |
| | | } |
| | | return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId; |
| | | } |
| | | |
| | | private TechnologyOperation getTechnologyOperation(Long technologyOperationId) { |
| | | if (technologyOperationId == null) { |
| | | return null; |
| | | } |
| | | return technologyOperationMapper.selectById(technologyOperationId); |
| | | } |
| | | |
| | | private String generateNextTaskNo() { |
| | | String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); |
| | | ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne( |
| | | Wrappers.<ProductionOperationTask>lambdaQuery() |
| | | .likeRight(ProductionOperationTask::getWorkOrderNo, "GD" + datePrefix) |
| | | .orderByDesc(ProductionOperationTask::getWorkOrderNo) |
| | | .last("limit 1")); |
| | | int sequenceNumber = 1; |
| | | if (latestTask != null && latestTask.getWorkOrderNo() != null && latestTask.getWorkOrderNo().startsWith("GD" + datePrefix)) { |
| | | try { |
| | | sequenceNumber = Integer.parseInt(latestTask.getWorkOrderNo().substring(("GD" + datePrefix).length())) + 1; |
| | | } catch (NumberFormatException ignored) { |
| | | sequenceNumber = 1; |
| | | } |
| | | } |
| | | return "GD" + String.format("%s%03d", datePrefix, sequenceNumber); |
| | | } |
| | | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private int compareDecimal(BigDecimal left, BigDecimal right) { |
| | | return defaultDecimal(left).compareTo(defaultDecimal(right)); |
| | | } |
| | | |
| | | /** |
| | | * å°æ å½¢ç»ææå¹³æå表ï¼ä¾¿äºç»ä¸ä¿åã |
| | | */ |
| | |
| | | import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; |
| | | import com.ruoyi.production.bean.vo.ProductionOperationTaskVo; |
| | | import com.ruoyi.production.mapper.ProductionOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper; |
| | | import com.ruoyi.production.mapper.ProductionOperationTaskMapper; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionOperationTask; |
| | | import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; |
| | | import com.ruoyi.production.service.ProductionOperationTaskService; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | |
| | | |
| | | private final SysUserMapper sysUserMapper; |
| | | private final ProductionOrderMapper productionOrderMapper; |
| | | private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; |
| | | |
| | | private final FileUtil fileUtil; |
| | | |
| | |
| | | // å页æ¥è¯¢ç产工åºä»»å¡ |
| | | Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); |
| | | IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto); |
| | | fillOperationTypes(result.getRecords()); |
| | | fillUserNames(result.getRecords()); |
| | | return result; |
| | | } |
| | |
| | | public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) { |
| | | // æ¥è¯¢å·¥åºä»»å¡å表 |
| | | List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class); |
| | | fillOperationTypes(result); |
| | | fillUserNames(result); |
| | | return result; |
| | | } |
| | |
| | | return null; |
| | | } |
| | | ProductionOperationTaskVo vo = BeanUtil.copyProperties(item, ProductionOperationTaskVo.class); |
| | | fillOperationTypes(Collections.singletonList(vo)); |
| | | if (item.getProductionOrderId() != null) { |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(item.getProductionOrderId()); |
| | | if (productionOrder != null) { |
| | |
| | | @Override |
| | | public List<ProductionOperationTaskVo> getOperation(ProductionOperationTaskDto dto) { |
| | | // æ¥è¯¢å·¥åºä»»å¡å表 |
| | | return baseMapper.getOperation(dto); |
| | | List<ProductionOperationTaskVo> result = baseMapper.getOperation(dto); |
| | | fillOperationTypes(result); |
| | | return result; |
| | | } |
| | | |
| | | private void fillOperationTypes(List<ProductionOperationTaskVo> voList) { |
| | | // åå¡«å·¥åºç±»åï¼0 è®¡æ¶ / 1 è®¡ä»¶ï¼ |
| | | if (voList == null || voList.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> operationIds = voList.stream() |
| | | .filter(Objects::nonNull) |
| | | .map(ProductionOperationTaskVo::getProductionOrderRoutingOperationId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toCollection(LinkedHashSet::new)); |
| | | if (operationIds.isEmpty()) { |
| | | return; |
| | | } |
| | | Map<Long, Integer> typeByOperationId = productionOrderRoutingOperationMapper |
| | | .selectBatchIds(new ArrayList<>(operationIds)) |
| | | .stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toMap( |
| | | ProductionOrderRoutingOperation::getId, |
| | | ProductionOrderRoutingOperation::getType, |
| | | (left, right) -> left |
| | | )); |
| | | for (ProductionOperationTaskVo vo : voList) { |
| | | if (vo == null || vo.getType() != null || vo.getProductionOrderRoutingOperationId() == null) { |
| | | continue; |
| | | } |
| | | vo.setType(typeByOperationId.get(vo.getProductionOrderRoutingOperationId())); |
| | | } |
| | | } |
| | | } |
| | |
| | | .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId()) |
| | | .orderByDesc(TechnologyRoutingOperation::getDragSort) |
| | | .orderByDesc(TechnologyRoutingOperation::getId)); |
| | | // Build task plan quantities from order BOM snapshot demand instead of recomputing from technology BOM units. |
| | | Long rootProductModelId = orderBom != null && orderBom.getProductModelId() != null |
| | | ? orderBom.getProductModelId() |
| | | : productionOrder.getProductModelId(); |
| | | List<ProductionBomStructure> orderBomStructureList = orderBom == null || orderBom.getId() == null |
| | | ? Collections.emptyList() |
| | | : productionBomStructureMapper.selectList( |
| | | Wrappers.<ProductionBomStructure>lambdaQuery() |
| | | .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId()) |
| | | .orderByAsc(ProductionBomStructure::getId)); |
| | | Map<String, BigDecimal> operationDemandedQuantityMap = |
| | | buildOperationDemandedQuantityMap(orderBomStructureList, rootProductModelId); |
| | | Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds( |
| | | // éåå¤çæ°æ®å¹¶ç»è£
ç»æ |
| | | routingOperations.stream() |
| | |
| | | ProductionOperationTask task = new ProductionOperationTask(); |
| | | task.setProductionOrderRoutingOperationId(targetOperation.getId()); |
| | | task.setProductionOrderId(productionOrder.getId()); |
| | | task.setPlanQuantity(defaultDecimal(productionOrder.getQuantity())); |
| | | task.setPlanQuantity(resolveTaskPlanQuantity( |
| | | sourceOperation, |
| | | operationDemandedQuantityMap, |
| | | productionOrder, |
| | | rootProductModelId)); |
| | | task.setCompleteQuantity(BigDecimal.ZERO); |
| | | task.setWorkOrderNo(generateNextTaskNo()); |
| | | task.setStatus(2); |
| | |
| | | return syncedParamCount; |
| | | } |
| | | |
| | | private Map<String, BigDecimal> buildOperationDemandedQuantityMap(List<ProductionBomStructure> bomStructures, |
| | | Long rootProductModelId) { |
| | | if (bomStructures == null || bomStructures.isEmpty()) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | Map<Long, ProductionBomStructure> structureById = bomStructures.stream() |
| | | .filter(item -> item != null && item.getId() != null) |
| | | .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left)); |
| | | Map<String, BigDecimal> demandedQuantityMap = new HashMap<>(); |
| | | Set<String> mergedOutputNodeKeySet = new HashSet<>(); |
| | | for (ProductionBomStructure bomStructure : bomStructures) { |
| | | if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) { |
| | | continue; |
| | | } |
| | | // The BOM row points to the producing operation; task quantity should come from that operation's output node. |
| | | ProductionBomStructure outputNode = resolveOperationOutputNode(bomStructure, structureById); |
| | | Long outputProductModelId = resolveOutputProductModelId(outputNode, rootProductModelId); |
| | | if (outputProductModelId == null) { |
| | | continue; |
| | | } |
| | | String mergedOutputNodeKey = buildOperationOutputNodeKey( |
| | | bomStructure.getTechnologyOperationId(), |
| | | outputNode == null ? null : outputNode.getId(), |
| | | outputProductModelId); |
| | | if (!mergedOutputNodeKeySet.add(mergedOutputNodeKey)) { |
| | | continue; |
| | | } |
| | | // demandedQuantity is already the order-level required output quantity for the current output node. |
| | | BigDecimal demandedQuantity = defaultDecimal(outputNode == null ? null : outputNode.getDemandedQuantity()); |
| | | String key = buildOperationDemandedQuantityKey(bomStructure.getTechnologyOperationId(), outputProductModelId); |
| | | demandedQuantityMap.merge(key, demandedQuantity, BigDecimal::add); |
| | | } |
| | | return demandedQuantityMap; |
| | | } |
| | | |
| | | private BigDecimal resolveTaskPlanQuantity(TechnologyRoutingOperation sourceOperation, |
| | | Map<String, BigDecimal> operationDemandedQuantityMap, |
| | | ProductionOrder productionOrder, |
| | | Long rootProductModelId) { |
| | | if (sourceOperation == null || operationDemandedQuantityMap == null || operationDemandedQuantityMap.isEmpty()) { |
| | | return defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); |
| | | } |
| | | Long outputProductModelId = sourceOperation.getProductModelId() != null |
| | | ? sourceOperation.getProductModelId() |
| | | : rootProductModelId; |
| | | String key = buildOperationDemandedQuantityKey(sourceOperation.getTechnologyOperationId(), outputProductModelId); |
| | | BigDecimal planQuantity = operationDemandedQuantityMap.get(key); |
| | | return planQuantity != null ? planQuantity : defaultDecimal(productionOrder == null ? null : productionOrder.getQuantity()); |
| | | } |
| | | |
| | | private String buildOperationDemandedQuantityKey(Long operationId, Long outputProductModelId) { |
| | | return String.valueOf(operationId) + "#" + String.valueOf(outputProductModelId); |
| | | } |
| | | |
| | | private String buildOperationOutputNodeKey(Long operationId, Long outputNodeId, Long outputProductModelId) { |
| | | return String.valueOf(operationId) + "#" + String.valueOf(outputNodeId) + "#" + String.valueOf(outputProductModelId); |
| | | } |
| | | |
| | | private ProductionBomStructure resolveOperationOutputNode(ProductionBomStructure bomStructure, |
| | | Map<Long, ProductionBomStructure> structureById) { |
| | | if (bomStructure == null) { |
| | | return null; |
| | | } |
| | | // The root node is the first output node; child rows use their direct parent as the current operation output. |
| | | if (bomStructure.getParentId() == null) { |
| | | return bomStructure; |
| | | } |
| | | ProductionBomStructure parent = structureById.get(bomStructure.getParentId()); |
| | | return parent != null ? parent : bomStructure; |
| | | } |
| | | |
| | | private Long resolveOutputProductModelId(ProductionBomStructure outputNode, |
| | | Long rootProductModelId) { |
| | | if (outputNode == null) { |
| | | return rootProductModelId; |
| | | } |
| | | return outputNode.getProductModelId() != null ? outputNode.getProductModelId() : rootProductModelId; |
| | | } |
| | | |
| | | private ProductionOrderBom syncProductionOrderBomSnapshot(ProductionOrder productionOrder, TechnologyRouting technologyRouting) { |
| | | // åæ¥è®¢åBOMå¿«ç
§ç»æ |
| | | if (technologyRouting.getBomId() == null) { |
| | |
| | | productionOrderBomMapper.insert(orderBom); |
| | | |
| | | Map<Long, Long> idMap = new HashMap<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | for (TechnologyBomStructure source : structureList) { |
| | | // åèç¹ parentId éè¦æ å°ææ°å¿«ç
§èç¹ idï¼æè½ä¿çåå§ BOM å±çº§ã |
| | | ProductionBomStructure target = new ProductionBomStructure(); |
| | |
| | | target.setProductModelId(source.getProductModelId()); |
| | | target.setTechnologyOperationId(source.getOperationId()); |
| | | target.setUnitQuantity(source.getUnitQuantity()); |
| | | target.setDemandedQuantity(source.getUnitQuantity().multiply(orderQuantity)); |
| | | target.setDemandedQuantity(lastProcessDemandedQuantity.multiply(source.getUnitQuantity())); |
| | | target.setUnit(source.getUnit()); |
| | | productionBomStructureMapper.insert(target); |
| | | idMap.put(source.getId(), target.getId()); |
| | | lastProcessDemandedQuantity = target.getDemandedQuantity(); |
| | | } |
| | | return orderBom; |
| | | } |
| | |
| | | if (reportOutput == null) { |
| | | continue; |
| | | } |
| | | Long reportMainId = reportOutput.getProductionProductMainId() != null |
| | | ? reportOutput.getProductionProductMainId() |
| | | : reportOutput.getProductMainId(); |
| | | if (reportMainId == null) { |
| | | if (reportOutput.getProductionProductMainId() == null) { |
| | | continue; |
| | | } |
| | | Long reportMainId = reportOutput.getProductionProductMainId(); |
| | | reportOutputMap.computeIfAbsent(reportMainId, k -> new ArrayList<>()).add(reportOutput); |
| | | } |
| | | |
| | |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.quality.mapper.*; |
| | | import com.ruoyi.quality.pojo.*; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationMapper; |
| | |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final StockUtils stockUtils; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | @Override |
| | |
| | | // å½åå®ç°æå·¥åºæåç´æ¥ä½ä¸ºæå
¥ï¼åç»è¥æ¥å
¥é¢æè®°å½å¯å¨è¿éæ¿æ¢æ¥æºã |
| | | ProductionProductInput productionProductInput = new ProductionProductInput(); |
| | | productionProductInput.setProductionProductMainId(productionProductMain.getId()); |
| | | productionProductInput.setProductMainId(productionProductMain.getId()); |
| | | productionProductInput.setProductModelId(item.getProductModelId()); |
| | | productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity()))); |
| | | productionProductInput.setQuantity(productionProductInput.getInputQuantity()); |
| | |
| | | |
| | | ProductionProductOutput productionProductOutput = new ProductionProductOutput(); |
| | | productionProductOutput.setProductionProductMainId(productionProductMain.getId()); |
| | | productionProductOutput.setProductMainId(productionProductMain.getId()); |
| | | productionProductOutput.setProductModelId(productModel.getId()); |
| | | productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity())); |
| | | productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty())); |
| | | productionProductOutputMapper.insert(productionProductOutput); |
| | | BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity()); |
| | | BigDecimal scrapQty = defaultDecimal(productionProductOutput.getScrapQty()); |
| | | BigDecimal productQty = reportQty; |
| | | String qualifiedBatchNo = null; |
| | | |
| | | List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( |
| | | Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() |
| | |
| | | stockInventoryDto.setQualitity(productQty); |
| | | stockInventoryDto.setProductModelId(productModel.getId()); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | qualifiedBatchNo = resolveLatestStockInBatchNo( |
| | | productionProductMain.getId(), |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), |
| | | productModel.getId(), |
| | | "0"); |
| | | } |
| | | |
| | | productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty)); |
| | |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | if (scrapQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addUnStockWithBatchNo( |
| | | productModel.getId(), |
| | | scrapQty, |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), |
| | | productionProductMain.getId(), |
| | | qualifiedBatchNo); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private String resolveLatestStockInBatchNo(Long recordId, |
| | | String recordType, |
| | | Long productModelId, |
| | | String stockType) { |
| | | if (recordId == null || productModelId == null) { |
| | | return null; |
| | | } |
| | | StockInRecord stockInRecord = stockInRecordService.getOne( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordId, recordId) |
| | | .eq(StockInRecord::getRecordType, recordType) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .eq(StockInRecord::getType, stockType) |
| | | .orderByDesc(StockInRecord::getId) |
| | | .last("limit 1"), |
| | | false); |
| | | if (stockInRecord == null) { |
| | | throw new ServiceException("æªæ¾å°å¯¹åºçå
¥åºç³è¯·è®°å½"); |
| | | } |
| | | return stockInRecord.getBatchNo(); |
| | | } |
| | | |
| | | private void syncOperationParamInputValue(ProductionProductMainDto dto, |
| | | Long productionOrderRoutingOperationId, |
| | | Long productionProductMainId) { |
| | |
| | | import com.ruoyi.project.system.domain.SysMenu;
|
| | | import com.ruoyi.project.system.domain.SysUser;
|
| | | import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
|
| | | import com.ruoyi.project.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.project.system.service.ISysMenuService; |
| | | import com.ruoyi.project.system.service.ISysUserDeptService; |
| | | import com.ruoyi.project.system.service.ISysUserService; |
| | | import com.ruoyi.project.system.mapper.SysDeptMapper;
|
| | | import com.ruoyi.project.system.service.ISysMenuService;
|
| | | import com.ruoyi.project.system.service.ISysUserDeptService;
|
| | | import com.ruoyi.project.system.service.ISysUserService;
|
| | | import lombok.AllArgsConstructor;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | | import org.springframework.util.ObjectUtils;
|
| | |
| | | {
|
| | | private SysLoginService loginService;
|
| | | private ISysMenuService menuService;
|
| | | private SysPermissionService permissionService; |
| | | private TokenService tokenService; |
| | | private ISysUserDeptService userDeptService; |
| | | private ISysUserService userService; |
| | | private SysDeptMapper sysDeptMapper; |
| | | private SysPermissionService permissionService;
|
| | | private TokenService tokenService;
|
| | | private ISysUserDeptService userDeptService;
|
| | | private ISysUserService userService;
|
| | | private SysDeptMapper sysDeptMapper;
|
| | |
|
| | | /**
|
| | | * ç»å½æ¹æ³
|
| | |
| | | public AjaxResult getInfo()
|
| | | {
|
| | | LoginUser loginUser = SecurityUtils.getLoginUser();
|
| | | SysUser user = userService.selectUserById(loginUser.getUserId()); |
| | | if (user == null) |
| | | { |
| | | user = loginUser.getUser(); |
| | | } |
| | | else |
| | | { |
| | | loginUser.setUser(user); |
| | | loginUser.setAiEnabled(user.getAiEnabled()); |
| | | tokenService.setLoginUser(loginUser); |
| | | } |
| | | SysUser user = loginUser.getUser();
|
| | | // è·åå½åç»å½å
¬å¸
|
| | | Long tenantId = loginUser.getTenantId();
|
| | | if(null != tenantId){
|
| | |
| | | loginUser.setPermissions(permissions);
|
| | | tokenService.refreshToken(loginUser);
|
| | | }
|
| | | AjaxResult ajax = AjaxResult.success(); |
| | | ajax.put("user", user); |
| | | ajax.put("aiEnabled", loginUser.getAiEnabled()); |
| | | ajax.put("roles", roles); |
| | | ajax.put("permissions", permissions); |
| | | return ajax; |
| | | AjaxResult ajax = AjaxResult.success();
|
| | | ajax.put("user", user);
|
| | | ajax.put("aiEnabled", loginUser.getAiEnabled());
|
| | | ajax.put("roles", roles);
|
| | | ajax.put("permissions", permissions);
|
| | | return ajax;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.service.CustomerFollowUpFileService; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void savePlan(SavePlanVo savePlanVo) { |
| | | Plan plan = BeanUtil.copyProperties(savePlanVo, Plan.class); |
| | | // éä»¶å¤ç |
| | | fileUtil.saveStorageAttachmentByRecordTypeAndRecordId(null, RecordTypeEnum.PLAN, savePlanVo.getId(), savePlanVo.getStorageBlobDTOs()); |
| | | if (savePlanVo.getId() == null) { |
| | | planMapper.insert(plan); |
| | | } else { |
| | | planMapper.updateById(plan); |
| | | } |
| | | // éä»¶å¤ç |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.PLAN, plan.getId(), savePlanVo.getStorageBlobDTOs()); |
| | | planService.savePlanNode(plan.getId(), savePlanVo.getSavePlanNodeList()); |
| | | } |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.service.CustomerFollowUpFileService; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | |
| | | @Transactional |
| | | public void save(@NotNull SaveInfoStageVo saveInfoStageVo) { |
| | | InfoStage infoStage = BeanUtil.copyProperties(saveInfoStageVo, InfoStage.class); |
| | | // éä»¶å¤ç |
| | | String attachmentIds = StrUtil.join(",", Optional.ofNullable(saveInfoStageVo.getAttachmentIds()).orElse(Collections.emptyList())); |
| | | infoStage.setAttachment(attachmentIds); |
| | | |
| | | fileUtil.saveStorageAttachmentByRecordTypeAndRecordId(null, RecordTypeEnum.INFO_STAGE, infoStage.getProjectManagementInfoId(), saveInfoStageVo.getStorageBlobDTOs()); |
| | | |
| | | if (infoStage.getId() == null) { |
| | | infoStageMapper.insert(infoStage); |
| | | } else { |
| | | infoStageMapper.updateById(infoStage); |
| | | } |
| | | |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.INFO_STAGE, infoStage.getId(), saveInfoStageVo.getStorageBlobDTOs()); |
| | | infoStageHandleService.syncInfoStage(infoStage.getProjectManagementInfoId()); |
| | | } |
| | | |
| | |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderDto; |
| | | import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; |
| | | import com.ruoyi.purchase.service.PurchaseReturnOrdersService; |
| | | import com.ruoyi.purchase.vo.PurchaseStockInProductVo; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | @GetMapping("/getByPurchaseLedgerId") |
| | | @Operation(summary = "éè´éè´§-æ ¹æ®éè´è®¢åidæ¥è¯¢éè´è®¢å对åºçå
¥åºäº§åä¿¡æ¯") |
| | | public AjaxResult getByPurchaseLedgerId(Long purchaseLedgerId) { |
| | | List<PurchaseStockInProductVo> purchaseStockInProductVos = purchaseReturnOrdersService.getByPurchaseLedgerId(purchaseLedgerId); |
| | | return AjaxResult.success(purchaseStockInProductVos); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | private String productName; |
| | | private String model; |
| | | private String unit; |
| | | //æ¹æ¬¡å· |
| | | private String batchNo; |
| | | |
| | | } |
| | |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class SimpleReturnOrderGroupDto implements Serializable { |
| | | private Long salesLedgerProductId; |
| | | private Long productModelId; |
| | | private BigDecimal sumReturnQuantity; |
| | | } |
| | |
| | | package com.ruoyi.purchase.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.bean.dto.PurchaseReturnDto; |
| | | import com.ruoyi.account.bean.vo.PurchaseReturnVo; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderDto; |
| | | import com.ruoyi.purchase.pojo.PurchaseReturnOrders; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto; |
| | | import com.ruoyi.purchase.pojo.PurchaseReturnOrders; |
| | | import com.ruoyi.purchase.vo.PurchaseReturnOrderProductsDetailVo; |
| | | import com.ruoyi.purchase.vo.PurchaseStockInProductVo; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | PurchaseReturnOrderHasAllInfoDto getPurchaseReturnOrderHasAllInfoById(@Param("id") @NotNull Long id); |
| | | |
| | | IPage<PurchaseReturnVo> listPageAccountPurchaseReturn(Page page, @Param("req") PurchaseReturnDto purchaseReturnDto); |
| | | |
| | | //æ ¹æ®éè´è®¢åidæ¥è¯¢éè´è®¢å对åºçå
¥åºäº§åä¿¡æ¯ |
| | | List<PurchaseStockInProductVo> getByPurchaseLedgerId(@Param("purchaseLedgerId") Long purchaseLedgerId); |
| | | |
| | | List<PurchaseReturnOrderProductsDetailVo> getPurchaseReturnOrderProductsDetailById(@Param("id") Long id); |
| | | } |
| | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.util.Date; |
| | | |
| | |
| | | */ |
| | | @Data |
| | | @TableName("product_record") |
| | | public class ProductRecord { |
| | | public class ProductRecord implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | |
| | | package com.ruoyi.purchase.pojo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * |
| | | * </p> |
| | | * |
| | | * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå
¬å¸ |
| | |
| | | @Schema(description = "éè´§åid") |
| | | private Long purchaseReturnOrderId; |
| | | |
| | | @Schema(description = "éè´äº§åid") |
| | | @Schema(description = "éå®å°è´¦äº§åid") |
| | | private Long salesLedgerProductId; |
| | | |
| | | @Schema(description = "éè´§æ°é") |
| | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | |
| | | @Schema(description = "å
³èå
¥åºåid") |
| | | private Long stockInRecordId; |
| | | |
| | | } |
| | |
| | | private Integer type; |
| | | |
| | | @Schema(description = "产åid") |
| | | private Integer productId; |
| | | private Long productId; |
| | | |
| | | @Schema(description = "åå·id") |
| | | private Integer productModelId; |
| | | private Long productModelId; |
| | | |
| | | private String register; |
| | | |
| | |
| | | import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto; |
| | | |
| | | import com.ruoyi.purchase.vo.PurchaseStockInProductVo; |
| | | import jakarta.validation.constraints.NotNull; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(@NotNull Long id); |
| | | |
| | | void deleteById(@NotNull Long id); |
| | | |
| | | List<PurchaseStockInProductVo> getByPurchaseLedgerId(Long purchaseLedgerId); |
| | | |
| | | } |
| | |
| | | package com.ruoyi.purchase.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.pojo.AccountIncome; |
| | | import com.ruoyi.account.service.AccountIncomeService; |
| | | import com.ruoyi.common.enums.SaleEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderDto; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderProductsDto; |
| | | import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; |
| | | import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper; |
| | | import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; |
| | | import com.ruoyi.purchase.pojo.PurchaseLedger; |
| | | import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts; |
| | | import com.ruoyi.purchase.pojo.PurchaseReturnOrders; |
| | | import com.ruoyi.purchase.service.PurchaseReturnOrdersService; |
| | | import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo; |
| | | import com.ruoyi.purchase.vo.PurchaseReturnOrderProductsDetailVo; |
| | | import com.ruoyi.purchase.vo.PurchaseStockInProductVo; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.sales.service.ISalesLedgerService; |
| | | import com.ruoyi.stock.mapper.StockOutRecordMapper; |
| | | import com.ruoyi.stock.pojo.StockOutRecord; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | purchaseReturnOrderProductsDto.setSalesLedgerProductId(purchaseReturnOrderProductsDto.getSalesLedgerProductId()); |
| | | purchaseReturnOrderProductsDto.setPurchaseReturnOrderId(purchaseReturnOrderDto.getId()); |
| | | purchaseReturnOrderProductsDto.setReturnQuantity(purchaseReturnOrderProductsDto.getReturnQuantity()); |
| | | purchaseReturnOrderProductsDto.setStockInRecordId(purchaseReturnOrderProductsDto.getStockInRecordId()); |
| | | // è¿é为æ°å¢å æ¤id为null |
| | | purchaseReturnOrderProductsDto.setId(null); |
| | | purchaseReturnOrderProductsMapper.insert(purchaseReturnOrderProductsDto); |
| | | //åºåéè¦åºåº(éè´éè´§) |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseReturnOrderDto.getPurchaseLedgerId()); |
| | | //åºåéè¦åºåº(éè´éè´§,å¸¦æ¹æ¬¡å·) |
| | | SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(purchaseReturnOrderProductsDto.getSalesLedgerProductId()); |
| | | stockUtils.substractStock(salesLedgerProduct.getProductModelId(), purchaseReturnOrderProductsDto.getReturnQuantity(), StockOutQualifiedRecordTypeEnum.PURCHASE_RETURN_STOCK_OUT.getCode(), purchaseReturnOrderDto.getId(), purchaseLedger.getPurchaseContractNumber()+"-"+salesLedgerProduct.getId()); |
| | | stockUtils.substractStock(salesLedgerProduct.getProductModelId(), purchaseReturnOrderProductsDto.getReturnQuantity(), StockOutQualifiedRecordTypeEnum.PURCHASE_RETURN_STOCK_OUT.getCode(), purchaseReturnOrderProductsDto.getId(), purchaseReturnOrderProductsDto.getBatchNo()); |
| | | } |
| | | }else { |
| | | throw new RuntimeException("è¯·éæ©éè´§åå"); |
| | |
| | | |
| | | @Override |
| | | public PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(Long id) { |
| | | //æ¥ä¸»ä½ |
| | | PurchaseReturnOrderHasAllInfoDto purchaseReturnOrders = purchaseReturnOrdersMapper.getPurchaseReturnOrderHasAllInfoById(id); |
| | | PurchaseReturnDetailsVo purchaseReturnOrderDto = BeanUtil.copyProperties(purchaseReturnOrders, PurchaseReturnDetailsVo.class); |
| | | // æ¥è¯¢åºä»å
·ä½å¯¹åºçéè´§ |
| | | LambdaQueryWrapper<PurchaseReturnOrderProducts> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, purchaseReturnOrders.getId()); |
| | | |
| | | List<PurchaseReturnOrderProducts> purchaseReturnOrderProducts = purchaseReturnOrderProductsMapper.selectList(queryWrapper); |
| | | List<PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVos = BeanUtil.copyToList(purchaseReturnOrderProducts, PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo.class); |
| | | // æ¥è¯¢åºå¯¹åºçååä¿¡æ¯ |
| | | List<Long> productIds = purchaseReturnOrderProductsDetailVos.stream().map(PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo::getSalesLedgerProductId).distinct().filter(Objects::nonNull).collect(Collectors.toList()); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerService.getSalesLedgerProductListByIds(productIds, SaleEnum.PURCHASE); |
| | | Map<Long, SalesLedgerProduct> productmap = salesLedgerProducts.stream().collect(Collectors.toMap(SalesLedgerProduct::getId, product -> product)); |
| | | purchaseReturnOrderProductsDetailVos.forEach(purchaseReturnOrderProductsDetailVo -> { |
| | | purchaseReturnOrderProductsDetailVo.setSalesLedgerProduct(productmap.get(purchaseReturnOrderProductsDetailVo.getSalesLedgerProductId())); |
| | | }); |
| | | |
| | | //æ¥æç» |
| | | List<PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVos = purchaseReturnOrdersMapper.getPurchaseReturnOrderProductsDetailById(id); |
| | | purchaseReturnOrderDto.setPurchaseReturnOrderProductsDetailVoList(purchaseReturnOrderProductsDetailVos); |
| | | |
| | | |
| | | return purchaseReturnOrderDto; |
| | | } |
| | | |
| | |
| | | @Transactional |
| | | public void deleteById(Long id) { |
| | | purchaseReturnOrdersMapper.deleteById(id); |
| | | List<PurchaseReturnOrderProducts> purchaseReturnOrderProducts = purchaseReturnOrderProductsMapper.selectList(Wrappers.<PurchaseReturnOrderProducts>lambdaQuery().eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, id)); |
| | | LambdaUpdateWrapper<PurchaseReturnOrderProducts> updateWrapper = new LambdaUpdateWrapper<>(); |
| | | updateWrapper.eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, id); |
| | | purchaseReturnOrderProductsMapper.delete(updateWrapper); |
| | | //(éè´éè´§çæ°æ®éè¦å æ) |
| | | stockOutRecordMapper.delete(Wrappers.<StockOutRecord>lambdaQuery() |
| | | .eq(StockOutRecord::getRecordType,StockOutQualifiedRecordTypeEnum.PURCHASE_RETURN_STOCK_OUT.getCode()) |
| | | .eq(StockOutRecord::getRecordId, id)); |
| | | purchaseReturnOrderProducts.stream().forEach(purchaseReturnOrderProducts1 -> { |
| | | stockUtils.deleteStockOutRecord(purchaseReturnOrderProducts1.getId(),StockOutQualifiedRecordTypeEnum.PURCHASE_RETURN_STOCK_OUT.getCode()); |
| | | }); |
| | | // è´¢å¡ |
| | | LambdaUpdateWrapper<AccountIncome> updateWrapperAccountIncome = new LambdaUpdateWrapper<>(); |
| | | updateWrapperAccountIncome.eq(AccountIncome::getBusinessId, id); |
| | |
| | | updateWrapperAccountIncome.eq(AccountIncome::getIncomeType, 4); |
| | | accountIncomeService.remove(updateWrapperAccountIncome); |
| | | } |
| | | |
| | | @Override |
| | | public List<PurchaseStockInProductVo> getByPurchaseLedgerId(Long purchaseLedgerId) { |
| | | return purchaseReturnOrdersMapper.getByPurchaseLedgerId(purchaseLedgerId); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.purchase.vo; |
| | | |
| | | import com.ruoyi.purchase.dto.PurchaseReturnOrderHasAllInfoDto; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | |
| | | private List<PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVoList; |
| | | |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public static class PurchaseReturnOrderProductsDetailVo implements Serializable { |
| | | private Long id; |
| | | private BigDecimal returnQuantity; |
| | | private Long salesLedgerProductId; |
| | | private Long purchaseReturnOrderId; |
| | | |
| | | private SalesLedgerProduct salesLedgerProduct; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.purchase.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | |
| | | |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class PurchaseReturnOrderProductsDetailVo { |
| | | |
| | | @Schema(description = "éè´§æç»id") |
| | | private Long id; |
| | | |
| | | @Schema(description = "éå®å°è´¦ç产åid") |
| | | private Long salesLedgerProductId; |
| | | |
| | | @Schema(description = "产åè§æ ¼id") |
| | | private Long productModelId; |
| | | |
| | | @Schema(description = "产å大类") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "è§æ ¼åå·") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "åä½") |
| | | private String unit; |
| | | |
| | | @Schema(description = "å
¥åºåå·") |
| | | private String inboundBatches; |
| | | |
| | | @Schema(description = "å
¥åºæ°é") |
| | | private BigDecimal stockInNum; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·") |
| | | private String batchNo; |
| | | |
| | | @Schema(description = "æªéè´§æ°") |
| | | private BigDecimal unQuantity; |
| | | |
| | | @Schema(description = "å·²éè´§æ°é") |
| | | private BigDecimal totalReturnNum; |
| | | |
| | | @Schema(description = "å«ç¨åä»·") |
| | | private BigDecimal taxInclusiveUnitPrice; |
| | | |
| | | @Schema(description = "éè´§æ°é") |
| | | private BigDecimal returnQuantity; |
| | | |
| | | @Schema(description = "éè´§åid") |
| | | private Long purchaseReturnOrderId; |
| | | |
| | | @Schema(description = "æ¯å¦è´¨æ£") |
| | | private Boolean isChecked; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.purchase.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | @Data |
| | | @Schema(name = "PurchaseStockInProductVo", description = "éè´ç®¡ç--éè´è®¢åä¸å
¥åºäº§åå表") |
| | | public class PurchaseStockInProductVo { |
| | | |
| | | @Schema(description = "å
¥åºåid") |
| | | private Long id; |
| | | |
| | | @Schema(description = "éå®å°è´¦ç产åid") |
| | | private Long salesLedgerProductId; |
| | | |
| | | @Schema(description = "产åè§æ ¼id") |
| | | private Long productModelId; |
| | | |
| | | @Schema(description = "产å大类") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "è§æ ¼åå·") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "åä½") |
| | | private String unit; |
| | | |
| | | @Schema(description = "å
¥åºåå·") |
| | | private String inboundBatches; |
| | | |
| | | @Schema(description = "å
¥åºæ°é") |
| | | private BigDecimal stockInNum; |
| | | |
| | | @Schema(description = "æ¹æ¬¡å·") |
| | | private String batchNo; |
| | | |
| | | @Schema(description = "å¯éè´§æ°") |
| | | private BigDecimal unQuantity; |
| | | |
| | | @Schema(description = "éè´§æ»æ°") |
| | | private BigDecimal totalReturnNum; |
| | | |
| | | @Schema(description = "å«ç¨åä»·") |
| | | private BigDecimal taxInclusiveUnitPrice; |
| | | |
| | | @Schema(description = "æ¯å¦è´¨æ£") |
| | | private Boolean isChecked; |
| | | } |
| | |
| | | /** |
| | | * æ°é |
| | | */ |
| | | @Excel(name = "æ°é") |
| | | @Excel(name = "æ»æ°é") |
| | | private BigDecimal quantity; |
| | | |
| | | @Excel(name = "åæ ¼æ°é") |
| | | @TableField("qualified_quantity") |
| | | private BigDecimal qualifiedQuantity; |
| | | |
| | | @Excel(name = "ä¸åæ ¼æ°é") |
| | | @TableField("unqualified_quantity") |
| | | private BigDecimal unqualifiedQuantity; |
| | | |
| | | /** |
| | | * æ£æµåä½ |
| | | */ |
| | |
| | | package com.ruoyi.quality.service.impl; |
| | | |
| | | |
| | | import cn.hutool.core.lang.Assert; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityInspectParam; |
| | | import com.ruoyi.quality.pojo.QualityUnqualified; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.quality.service.IQualityInspectParamService; |
| | | import com.ruoyi.quality.service.IQualityInspectService; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | |
| | | |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.math.BigDecimal; |
| | | import java.net.URLEncoder; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | |
| | | |
| | | private final StockUtils stockUtils; |
| | | private final StockInventoryService stockInventoryService; |
| | | private final StockInRecordService stockInRecordService; |
| | | private QualityInspectMapper qualityInspectMapper; |
| | | |
| | | private IQualityInspectParamService qualityInspectParamService; |
| | |
| | | if (ObjectUtils.isNull(qualityInspect.getCheckResult())) { |
| | | throw new RuntimeException("请å
夿æ¯å¦åæ ¼"); |
| | | } |
| | | /*夿ä¸åæ ¼*/ |
| | | if (qualityInspect.getCheckResult().equals("ä¸åæ ¼")) { |
| | | QualityUnqualified qualityUnqualified = new QualityUnqualified(); |
| | | BeanUtils.copyProperties(qualityInspect, qualityUnqualified); |
| | | qualityUnqualified.setInspectState(0);//å¾
å¤ç |
| | | qualityUnqualified.setProductModelId(qualityInspect.getProductModelId()); |
| | | List<QualityInspectParam> inspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId())); |
| | | String text = inspectParams.stream().map(QualityInspectParam::getParameterItem).collect(Collectors.joining(",")); |
| | | qualityUnqualified.setDefectivePhenomena(text + "è¿äºææ ä¸åå¨ä¸åæ ¼");//ä¸åæ ¼ç°è±¡ |
| | | qualityUnqualified.setInspectId(qualityInspect.getId()); |
| | | qualityUnqualifiedMapper.insert(qualityUnqualified); |
| | | } else { |
| | | |
| | | // åºååæ ¼æ°é以åä¸åæ ¼å¤çè¿è¡å¯¹åºçå¤ç |
| | | Assert.isTrue(qualityInspect.getQuantity().compareTo(qualityInspect.getQualifiedQuantity().add(qualityInspect.getUnqualifiedQuantity())) == 0,"è¯·æ£æ¥åæ ¼æ°éåä¸åæ ¼æ°éï¼éè¦åæ ¼æ°é+ä¸åæ ¼æ°é䏿»æ°ä¿æä¸è´"); |
| | | if(qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){ |
| | | //åæ ¼ç´æ¥å
¥åº |
| | | // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId()); |
| | | //ä»
æ·»å å
¥åºè®°å½ |
| | |
| | | } |
| | | stockInventoryDto.setRecordId(qualityInspect.getId()); |
| | | stockInventoryDto.setProductModelId(qualityInspect.getProductModelId()); |
| | | stockInventoryDto.setQualitity(qualityInspect.getQuantity()); |
| | | stockInventoryDto.setQualitity(qualityInspect.getQualifiedQuantity()); |
| | | stockInventoryDto.setBatchNo(resolveProductionBatchNo( |
| | | qualityInspect.getProductMainId(), |
| | | qualityInspect.getId(), |
| | | qualityInspect.getProductModelId())); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } |
| | | if(qualityInspect.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){ |
| | | QualityUnqualified qualityUnqualified = new QualityUnqualified(); |
| | | BeanUtils.copyProperties(qualityInspect, qualityUnqualified); |
| | | qualityUnqualified.setInspectState(0);//å¾
å¤ç |
| | | qualityUnqualified.setQuantity(qualityInspect.getUnqualifiedQuantity()); |
| | | List<QualityInspectParam> inspectParams = qualityInspectParamService.list(Wrappers.<QualityInspectParam>lambdaQuery().eq(QualityInspectParam::getInspectId, inspect.getId())); |
| | | String text = inspectParams.stream().map(QualityInspectParam::getParameterItem).collect(Collectors.joining(",")); |
| | | qualityUnqualified.setDefectivePhenomena(text + "è¿äºææ ä¸åå¨ä¸åæ ¼");//ä¸åæ ¼ç°è±¡ |
| | | qualityUnqualified.setInspectId(qualityInspect.getId()); |
| | | qualityUnqualifiedMapper.insert(qualityUnqualified); |
| | | } |
| | | |
| | | qualityInspect.setInspectState(1);//å·²æäº¤ |
| | | return qualityInspectMapper.updateById(qualityInspect); |
| | | } |
| | | |
| | | private String resolveProductionBatchNo(Long productionProductMainId, |
| | | Long qualityInspectId, |
| | | Long productModelId) { |
| | | if (productModelId == null) { |
| | | return null; |
| | | } |
| | | if (productionProductMainId != null) { |
| | | StockInRecord productionRecord = stockInRecordService.getOne( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordId, productionProductMainId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .in(StockInRecord::getRecordType, Arrays.asList( |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode())) |
| | | .isNotNull(StockInRecord::getBatchNo) |
| | | .orderByDesc(StockInRecord::getId) |
| | | .last("limit 1"), |
| | | false); |
| | | if (productionRecord != null) { |
| | | return productionRecord.getBatchNo(); |
| | | } |
| | | } |
| | | if (qualityInspectId == null) { |
| | | return null; |
| | | } |
| | | StockInRecord inspectRecord = stockInRecordService.getOne( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordId, qualityInspectId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .eq(StockInRecord::getRecordType, StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()) |
| | | .isNotNull(StockInRecord::getBatchNo) |
| | | .orderByDesc(StockInRecord::getId) |
| | | .last("limit 1"), |
| | | false); |
| | | return inspectRecord == null ? null : inspectRecord.getBatchNo(); |
| | | } |
| | | |
| | | /*çææ£éªæ¥å*/ |
| | | @Override |
| | | public void down(HttpServletResponse response, QualityInspect qualityInspect) { |
| | |
| | | import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityUnqualified; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.quality.service.IQualityInspectService; |
| | | import com.ruoyi.quality.service.IQualityUnqualifiedService; |
| | | import com.ruoyi.stock.service.StockUninventoryService; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; |
| | | private final ProductionOperationTaskMapper productionOperationTaskMapper; |
| | | private final StockUninventoryService stockUninventoryService; |
| | | private final StockInRecordService stockInRecordService; |
| | | |
| | | @Override |
| | | public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) { |
| | |
| | | public int deal(QualityUnqualified qualityUnqualified) { |
| | | QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId()); |
| | | QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId()); |
| | | String batchNo = qualityInspect == null ? null |
| | | : resolveProductionBatchNo(qualityInspect.getProductMainId(), qualityInspect.getId(), qualityInspect.getProductModelId()); |
| | | if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) { |
| | | switch (qualityUnqualified.getDealResult()) { |
| | | case "è¿ä¿®": |
| | |
| | | } |
| | | break; |
| | | case "æ¥åº": |
| | | stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId()); |
| | | stockUtils.addUnStockWithBatchNo(qualityInspect.getProductModelId(), unqualified.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId(), batchNo); |
| | | break; |
| | | case "è®©æ¥æ¾è¡": |
| | | stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId()); |
| | | stockUtils.addStockWithBatchNo(qualityInspect.getProductModelId(), unqualified.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId(), batchNo); |
| | | break; |
| | | default: |
| | | break; |
| | |
| | | private BigDecimal defaultDecimal(BigDecimal value) { |
| | | return value == null ? BigDecimal.ZERO : value; |
| | | } |
| | | |
| | | private String resolveProductionBatchNo(Long productionProductMainId, |
| | | Long qualityInspectId, |
| | | Long productModelId) { |
| | | if (productModelId == null) { |
| | | return null; |
| | | } |
| | | if (productionProductMainId != null) { |
| | | StockInRecord productionRecord = stockInRecordService.getOne( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordId, productionProductMainId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .in(StockInRecord::getRecordType, Arrays.asList( |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), |
| | | StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode())) |
| | | .isNotNull(StockInRecord::getBatchNo) |
| | | .orderByDesc(StockInRecord::getId) |
| | | .last("limit 1"), |
| | | false); |
| | | if (productionRecord != null) { |
| | | return productionRecord.getBatchNo(); |
| | | } |
| | | } |
| | | if (qualityInspectId == null) { |
| | | return null; |
| | | } |
| | | StockInRecord inspectRecord = stockInRecordService.getOne( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordId, qualityInspectId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .eq(StockInRecord::getRecordType, StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()) |
| | | .isNotNull(StockInRecord::getBatchNo) |
| | | .orderByDesc(StockInRecord::getId) |
| | | .last("limit 1"), |
| | | false); |
| | | return inspectRecord == null ? null : inspectRecord.getBatchNo(); |
| | | } |
| | | } |
| | |
| | | if (CollUtil.isEmpty(list)) { |
| | | return AjaxResult.success(list); |
| | | } |
| | | List<Long> productIds = list.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList()); |
| | | List<Long> productIds = list.stream().map(SalesLedgerProduct::getProductModelId).collect(Collectors.toList()); |
| | | List<SimpleReturnOrderGroupDto> groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds); |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, item -> item.getSumReturnQuantity())); |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getProductModelId, item -> item.getSumReturnQuantity())); |
| | | |
| | | list.forEach(item -> { |
| | | if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) { |
| | |
| | | } |
| | | } |
| | | // ç»è®¡éè´§æ°é |
| | | BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO); |
| | | BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getProductModelId(), BigDecimal.ZERO); |
| | | item.setReturnQuality(returnQuality); |
| | | item.setAvailableQuality(item.getQuantity().subtract(returnQuality)); |
| | | }); |
| | |
| | | |
| | | |
| | | @GetMapping("/getByCustomerName") |
| | | @Operation(summary = "éè¿å®¢æ·åç§°æ¥è¯¢") |
| | | @Operation(summary = "éè¿å®¢æ·åç§°æ¥è¯¢å
³èçåè´§åå·") |
| | | public AjaxResult getByCustomerName(String customerName) { |
| | | return AjaxResult.success(shippingInfoService.getShippingInfoByCustomerName(customerName)); |
| | | } |
| | |
| | | import com.ruoyi.sales.pojo.ShippingProductDetail; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | private List<Long> batchNo; |
| | | private List<ShippingProductDetail> batchNoDetailList; |
| | | |
| | | //å
³èçåºåºåå· |
| | | private String outboundBatches; |
| | | |
| | | //åè´§æ°é |
| | | private BigDecimal totalQuantity; |
| | | |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.sales.dto.SalesLedgerProductDto; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingProductVo; |
| | | import com.ruoyi.sales.dto.ShippingInfoDto; |
| | | import com.ruoyi.sales.pojo.ShippingInfo; |
| | | import org.apache.ibatis.annotations.Param; |
| | |
| | | |
| | | List<ShippingInfo> listAll(); |
| | | |
| | | List<SalesLedgerProductDto> getReturnManagementDtoById(@Param("shippingId")Long shippingId); |
| | | List<ShippingProductVo> getReturnManagementDtoById(@Param("shippingId")Long shippingId); |
| | | |
| | | List<ShippingInfo> getShippingInfoByCustomerName(String customerName); |
| | | } |
| | |
| | | private Long id; |
| | | @Schema(description = "é宿¥ä»·åid") |
| | | private Long salesQuotationId; |
| | | |
| | | @Schema(description = "产åId") |
| | | @TableField(value = "product_id") |
| | | private Long productId; |
| | | @Schema(description = "产åè§æ ¼Id") |
| | | @TableField(value = "product_model_id") |
| | | private Long productModelId; |
| | | @Schema(description = "åååç§°") |
| | | private String product; |
| | | @Schema(description = "ååè§æ ¼") |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.sales.dto.SalesLedgerProductDto; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingProductVo; |
| | | import com.ruoyi.sales.dto.ShippingApproveDto; |
| | | import com.ruoyi.sales.dto.ShippingInfoDto; |
| | | import com.ruoyi.sales.dto.ShippingProductDetailDto; |
| | |
| | | |
| | | boolean delete(List<Long> ids); |
| | | |
| | | List<SalesLedgerProductDto> getReturnManagementDtoById( Long shippingId); |
| | | List<ShippingProductVo> getReturnManagementDtoById(Long shippingId); |
| | | |
| | | List<ShippingInfo> getShippingInfoByCustomerName(String customerName); |
| | | |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.service.AccountIncomeService; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | import com.ruoyi.basic.mapper.CustomerMapper; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.enums.SaleEnum; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final RedisTemplate<String, String> redisTemplate; |
| | | private final FileUtil fileUtil; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | @Value("${file.upload-dir}") |
| | |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper); |
| | | if (type.equals(SaleEnum.PURCHASE)) { |
| | | // æ¥è¯¢éè´§ä¿¡æ¯ |
| | | List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList()); |
| | | List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getProductModelId).collect(Collectors.toList()); |
| | | List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>(); |
| | | if(CollectionUtils.isNotEmpty(productIds)){ |
| | | groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds); |
| | | } |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity)); |
| | | Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getProductModelId, SimpleReturnOrderGroupDto::getSumReturnQuantity)); |
| | | salesLedgerProducts.forEach(item -> { |
| | | BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO); |
| | | BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getProductModelId(), BigDecimal.ZERO); |
| | | item.setReturnQuality(returnQuality); |
| | | item.setAvailableQuality(item.getQuantity().subtract(returnQuality)); |
| | | }); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto) { |
| | | try { |
| | | // 1. æ ¡éªå®¢æ·ä¿¡æ¯ |
| | | Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId()); |
| | | if (customer == null) { |
| | | throw new BaseException("客æ·ä¸åå¨"); |
| | | } |
| | | |
| | | // 2. DTO转Entity |
| | | SalesLedger salesLedger = convertToEntity(salesLedgerDto); |
| | | salesLedger.setCustomerName(customer.getCustomerName()); |
| | | salesLedger.setTenantId(customer.getTenantId()); |
| | | // 3. æ°å¢ææ´æ°ä¸»è¡¨ |
| | | if (salesLedger.getId() == null) { |
| | | String contractNo = generateSalesContractNo(); |
| | | salesLedger.setSalesContractNo(contractNo); |
| | | salesLedgerMapper.insert(salesLedger); |
| | | } else { |
| | | salesLedgerMapper.updateById(salesLedger); |
| | | } |
| | | |
| | | // 4. å¤çåè¡¨æ°æ® |
| | | List<SalesLedgerProduct> productList = salesLedgerDto.getProductData(); |
| | | if (productList != null && !productList.isEmpty()) { |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType())); |
| | | updateMainContractAmount( |
| | | salesLedger.getId(), |
| | | productList, |
| | | SalesLedgerProduct::getTaxInclusiveTotalPrice, |
| | | salesLedgerMapper, |
| | | SalesLedger.class |
| | | ); |
| | | } |
| | | |
| | | // 5. è¿ç§»ä¸´æ¶æä»¶å°æ£å¼ç®å½ |
| | | if (salesLedgerDto.getTempFileIds() != null && !salesLedgerDto.getTempFileIds().isEmpty()) { |
| | | migrateTempFilesToFormal(salesLedger.getId(), salesLedgerDto.getTempFileIds()); |
| | | } |
| | | return 1; |
| | | } catch (IOException e) { |
| | | throw new BaseException("æä»¶è¿ç§»å¤±è´¥: " + e.getMessage()); |
| | | // 1. æ ¡éªå®¢æ·ä¿¡æ¯ |
| | | Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId()); |
| | | if (customer == null) { |
| | | throw new BaseException("客æ·ä¸åå¨"); |
| | | } |
| | | |
| | | // 2. DTO转Entity |
| | | SalesLedger salesLedger = convertToEntity(salesLedgerDto); |
| | | salesLedger.setCustomerName(customer.getCustomerName()); |
| | | salesLedger.setTenantId(customer.getTenantId()); |
| | | // 3. æ°å¢ææ´æ°ä¸»è¡¨ |
| | | if (salesLedger.getId() == null) { |
| | | String contractNo = generateSalesContractNo(); |
| | | salesLedger.setSalesContractNo(contractNo); |
| | | salesLedgerMapper.insert(salesLedger); |
| | | } else { |
| | | salesLedgerMapper.updateById(salesLedger); |
| | | } |
| | | |
| | | |
| | | // 4. å¤çåè¡¨æ°æ® |
| | | List<SalesLedgerProduct> productList = salesLedgerDto.getProductData(); |
| | | if (productList != null && !productList.isEmpty()) { |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType())); |
| | | updateMainContractAmount( |
| | | salesLedger.getId(), |
| | | productList, |
| | | SalesLedgerProduct::getTaxInclusiveTotalPrice, |
| | | salesLedgerMapper, |
| | | SalesLedger.class |
| | | ); |
| | | } |
| | | |
| | | // 5. ä¿åéå®å°è´¦éä»¶ |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, salesLedger.getId(), salesLedgerDto.getStorageBlobDTOs()); |
| | | |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | | * |
| | | * @param businessId ä¸å¡IDï¼éå®å°è´¦IDï¼ |
| | | * @param tempFileIds ä¸´æ¶æä»¶IDå表 |
| | | * @throws IOException æä»¶æä½å¼å¸¸ |
| | | */ |
| | | private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { |
| | | if (CollectionUtils.isEmpty(tempFileIds)) { |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ£å¼ç®å½è·¯å¾ï¼æä¸å¡ç±»å忥æåç»ï¼ |
| | | String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | Path formalDirPath = Paths.get(formalDir); |
| | | |
| | | // ç¡®ä¿æ£å¼ç®å½åå¨ï¼éå½åå»ºï¼ |
| | | if (!Files.exists(formalDirPath)) { |
| | | Files.createDirectories(formalDirPath); |
| | | } |
| | | |
| | | for (String tempFileId : tempFileIds) { |
| | | // æ¥è¯¢ä¸´æ¶æä»¶è®°å½ |
| | | TempFile tempFile = tempFileMapper.selectById(tempFileId); |
| | | if (tempFile == null) { |
| | | log.warn("ä¸´æ¶æä»¶ä¸åå¨ï¼è·³è¿å¤ç: {}", tempFileId); |
| | | continue; |
| | | } |
| | | |
| | | // æå»ºæ£å¼æä»¶åï¼å
å«ä¸å¡IDåæ¶é´æ³ï¼é¿å
å²çªï¼ |
| | | String originalFilename = tempFile.getOriginalName(); |
| | | String fileExtension = FilenameUtils.getExtension(originalFilename); |
| | | String formalFilename = businessId + "_" + |
| | | System.currentTimeMillis() + "_" + |
| | | UUID.randomUUID().toString().substring(0, 8) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // æ§è¡æä»¶è¿ç§»ï¼ä½¿ç¨ååæä½ç¡®ä¿å®å
¨æ§ï¼ |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // ååç§»å¨å¤±è´¥ï¼ä½¿ç¨å¤å¶+å é¤ |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | |
| | | // æ´æ°æä»¶è®°å½ï¼å
³èå°ä¸å¡IDï¼ |
| | | CommonFile fileRecord = new CommonFile(); |
| | | fileRecord.setCommonId(businessId); |
| | | fileRecord.setName(originalFilename); |
| | | fileRecord.setUrl(formalFilePath.toString()); |
| | | fileRecord.setCreateTime(LocalDateTime.now()); |
| | | //éå® |
| | | fileRecord.setType(FileNameType.SALE.getValue()); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // å é¤ä¸´æ¶æä»¶è®°å½ |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("æä»¶è¿ç§»æå: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("æä»¶è¿ç§»å¤±è´¥: {}", tempFile.getTempPath(), e); |
| | | // å¯éæ©åæ»äºå¡æè®°å½å¤±è´¥æä»¶ |
| | | throw new IOException("æä»¶è¿ç§»å¼å¸¸", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æä»¶è¿ç§»æ¹æ³ |
| | | |
| | | @Override |
| | | public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) { |
| | |
| | | import com.ruoyi.approve.bean.vo.ApproveProcessVO; |
| | | import com.ruoyi.basic.mapper.CustomerMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.common.enums.IsDeleteEnum; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | |
| | | // å 餿¥ä»·å®¡æ¹ |
| | | ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>() |
| | | .eq(ApproveProcess::getApproveType, 6) |
| | | .eq(ApproveProcess::getApproveDelete, IsDeleteEnum.NOT_DELETED) |
| | | .eq(ApproveProcess::getApproveReason, salesQuotation.getQuotationNo())); |
| | | if(one != null){ |
| | | approveProcessService.delByIds(Collections.singletonList(one.getId())); |
| | |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.procurementrecord.bean.vo.ShippingProductVo; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.sales.dto.SalesLedgerProductDto; |
| | | import com.ruoyi.sales.dto.ShippingApproveDto; |
| | | import com.ruoyi.sales.dto.ShippingInfoDto; |
| | | import com.ruoyi.sales.dto.ShippingProductDetailDto; |
| | |
| | | if (CollectionUtils.isEmpty(shippingInfos)) return false; |
| | | // å é¤éä»¶ |
| | | commonFileService.deleteByBusinessIds(ids, FileNameType.SHIP.getValue()); |
| | | // æ£å·²åè´§åºå |
| | | for (ShippingInfo shippingInfo : shippingInfos) { |
| | | if ("å·²åè´§".equals(shippingInfo.getStatus())) { |
| | | stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode()); |
| | | } |
| | | } |
| | | // å é¤åè´§å®¡æ¹ |
| | | if (CollectionUtils.isNotEmpty(shippingInfos)) { |
| | | for (ShippingInfo shippingInfo : shippingInfos) { |
| | |
| | | List<Long> list = one.stream().map(ApproveProcess::getId).toList(); |
| | | approveProcessService.delByIds(list); |
| | | } |
| | | // æ£å·²åè´§åºå |
| | | stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode()); |
| | | } |
| | | } |
| | | //å é¤åè´§æç» |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<SalesLedgerProductDto> getReturnManagementDtoById(Long shippingId) { |
| | | public List<ShippingProductVo> getReturnManagementDtoById(Long shippingId) { |
| | | return shippingInfoMapper.getReturnManagementDtoById(shippingId); |
| | | |
| | | } |
| | |
| | | return R.ok(stockInventoryDtoIPage); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯¹åºæ¹å·åæ°é |
| | | * @param page |
| | | * @param stockInventoryDto |
| | | * @return |
| | | */ |
| | | @GetMapping("/getBatchNoQty") |
| | | @Operation(summary = "æ¥è¯¢å¯¹åºæ¹å·åæ°é") |
| | | public R getBatchNoQty(Page page, StockInventoryDto stockInventoryDto) { |
| | | IPage<StockInventoryDto> stockInventoryDtoIPage = stockInventoryService.getBatchNoQty(page, stockInventoryDto); |
| | | return R.ok(stockInventoryDtoIPage); |
| | | } |
| | | |
| | | @PostMapping("/addstockInventory") |
| | | @Operation(summary = "æ°å¢åºå") |
| | | public R addstockInventory(@RequestBody StockInventoryDto stockInventoryDto) { |
| | |
| | | } |
| | | |
| | | |
| | | @PostMapping("importStockInventory") |
| | | @PostMapping("/importStockInventory") |
| | | @Operation(summary = "导å
¥åºå") |
| | | public R importStockInventory(MultipartFile file) { |
| | | return stockInventoryService.importStockInventory(file); |
| | |
| | | stockInventoryService.exportStockInventory(response, stockInventoryDto); |
| | | } |
| | | |
| | | @GetMapping("stockInventoryPage") |
| | | @GetMapping("/stockInventoryPage") |
| | | @Operation(summary = "åºåæ¥è¡¨æ¥è¯¢") |
| | | public R stockInventoryPage(Page page, StockInventoryDto stockInventoryDto) { |
| | | return R.ok(stockInventoryService.stockInventoryPage(stockInventoryDto,page)); |
| | | } |
| | | |
| | | @GetMapping("stockInAndOutRecord") |
| | | @GetMapping("/stockInAndOutRecord") |
| | | @Operation(summary = "ç»è®¡å个产åçå
¥åºååºåºè®°å½") |
| | | public R stockInAndOutRecord(StockInventoryDto stockInventoryDto,Page page) { |
| | | return R.ok(stockInventoryService.stockInAndOutRecord(stockInventoryDto,page)); |
| | |
| | | public R thawStock(@RequestBody StockInventoryDto stockInventoryDto) { |
| | | return R.ok(stockInventoryService.thawStock(stockInventoryDto)); |
| | | } |
| | | |
| | | |
| | | @GetMapping("/getByModelId") |
| | | @Operation(summary = "æ ¹æ®äº§åè§æ ¼IDè·åå
¥åºè®°å½") |
| | |
| | | |
| | | @Schema(description = "ä¸åæ ¼åºåID") |
| | | private Long unQualifiedId; |
| | | |
| | | @Schema(description = "产åid") |
| | | private Long productId; |
| | | } |
| | |
| | | private String model; |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | @Excel(name = "æ¹å·") |
| | | private String batchNo; |
| | | @Excel(name = "å
¥åºæ¥æº") |
| | | private String recordType; |
| | | @Excel(name = "å
¥åºæ°é") |
| | | private String stockInNum; |
| | | @Excel(name = "å
¥åºæ¶é´") |
| | | @Excel(name = "å
¥åºæ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private LocalDateTime createTime; |
| | |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | |
| | | @Excel(name = "æ¹å·") |
| | | private String batchNo; |
| | | |
| | | |
| | | @Excel(name = "åæ ¼åºåæ°é") |
| | | private BigDecimal qualifiedQuantity; |
| | | |
| | |
| | | private String model; |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | @Excel(name = "æ¹å·") |
| | | private String batchNo; |
| | | @Excel(name = "åºåºæ¥æº") |
| | | private String recordType; |
| | | @Excel(name = "åºåºæ°é") |
| | | private String stockInNum; |
| | | @Excel(name = "åºåºæ¶é´") |
| | | private String stockOutNum; |
| | | @Excel(name = "åºåºæ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private LocalDateTime createTime; |
| | |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | |
| | | @Excel(name = "æ¹å·") |
| | | private String batchNo; |
| | | @Excel(name = "åºåæ°é") |
| | | private BigDecimal qualitity; |
| | | |
| | |
| | | List<StockInventory> listSelectableBatchNoByProductModelIds(@Param("productModelIds") List<Long> productModelIds); |
| | | |
| | | List<StockInventory> getByModelId(@Param("productModelId") Long productModelId); |
| | | |
| | | IPage<StockInventoryDto> getBatchNoQty(Page page, @Param("ew") StockInventoryDto stockInventoryDto); |
| | | } |
| | |
| | | Boolean thawStock(StockInventoryDto stockInventoryDto); |
| | | |
| | | List<StockInventory> getByModelId(Long modelId); |
| | | |
| | | IPage<StockInventoryDto> getBatchNoQty(Page page, StockInventoryDto stockInventoryDto); |
| | | } |
| | |
| | | public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) { |
| | | List<StockInRecordExportData> list = stockInRecordMapper.listStockInRecordExportData(stockInRecordDto); |
| | | for (StockInRecordExportData stockInRecordExportData : list) { |
| | | if (stockInRecordExportData.getType().equals("0")) { |
| | | if (!stockInRecordExportData.getType().equals("0")) { |
| | | stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockOutQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue()); |
| | | }else { |
| | | stockInRecordExportData.setRecordType(EnumUtil.fromCode(StockInQualifiedRecordTypeEnum.class, Integer.parseInt(stockInRecordExportData.getRecordType())).getValue()); |
| | |
| | | import com.ruoyi.stock.service.StockOutRecordService; |
| | | import com.ruoyi.stock.service.StockUninventoryService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | |
| | | * @since 2026-01-21 04:16:36 |
| | | */ |
| | | @Service |
| | | @AllArgsConstructor |
| | | @RequiredArgsConstructor |
| | | public class StockInventoryServiceImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryService { |
| | | |
| | | private StockInventoryMapper stockInventoryMapper; |
| | | private StockInRecordService stockInRecordService; |
| | | private StockOutRecordService stockOutRecordService; |
| | | private StockUninventoryService stockUninventoryService; |
| | | private SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private ProductModelMapper productModelMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockOutRecordService stockOutRecordService; |
| | | private final StockUninventoryService stockUninventoryService; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final ProductModelMapper productModelMapper; |
| | | |
| | | @Override |
| | | public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) { |
| | | return stockInventoryMapper.pagestockInventory(page, stockInventoryDto); |
| | |
| | | newStockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity()); |
| | | newStockInventory.setWarnNum(stockInventoryDto.getWarnNum()); |
| | | stockInventoryMapper.insert(newStockInventory); |
| | | }else { |
| | | stockInventoryMapper.updateAddStockInventory(stockInventoryDto); |
| | | } else { |
| | | stockInventoryMapper.updateAddStockInventory(stockInventoryDto); |
| | | } |
| | | return true; |
| | | } |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) { |
| | | LambdaQueryWrapper<StockInventory> eq = new QueryWrapper<StockInventory>().lambda() |
| | | .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()); |
| | | .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()); |
| | | if (StringUtils.isEmpty(stockInventoryDto.getBatchNo())) { |
| | | eq.isNull(StockInventory::getBatchNo); |
| | | stockInventoryDto.setBatchNo(null); |
| | |
| | | } |
| | | |
| | | stockInventoryDto.setProductModelId(matchedProduct.getProductModelId()); |
| | | this.addstockInventory(stockInventoryDto); |
| | | this.addStockInRecordOnly(stockInventoryDto); |
| | | successCount++; |
| | | } |
| | | |
| | |
| | | |
| | | List<StockInventoryExportData> list = stockInventoryMapper.listStockInventoryExportData(stockInventoryDto); |
| | | ExcelUtil<StockInventoryExportData> util = new ExcelUtil<>(StockInventoryExportData.class); |
| | | util.exportExcel(response,list, "åºåä¿¡æ¯"); |
| | | util.exportExcel(response, list, "åºåä¿¡æ¯"); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<StockInRecordDto> stockInventoryPage(StockInventoryDto stockInventoryDto, Page page) { |
| | | return stockInventoryMapper.stockInventoryPage(stockInventoryDto,page); |
| | | return stockInventoryMapper.stockInventoryPage(stockInventoryDto, page); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<StockInventoryDto> stockInAndOutRecord(StockInventoryDto stockInventoryDto, Page page) { |
| | | return stockInventoryMapper.stockInAndOutRecord(stockInventoryDto,page); |
| | | return stockInventoryMapper.stockInAndOutRecord(stockInventoryDto, page); |
| | | } |
| | | |
| | | @Override |
| | | public Boolean frozenStock(StockInventoryDto stockInventoryDto) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectById(stockInventoryDto.getId()); |
| | | if (stockInventory.getQualitity().compareTo(stockInventoryDto.getLockedQuantity())<0) { |
| | | if (stockInventory.getQualitity().compareTo(stockInventoryDto.getLockedQuantity()) < 0) { |
| | | throw new RuntimeException("å»ç»æ°éä¸è½è¶
è¿åºåæ°é"); |
| | | } |
| | | if (ObjectUtils.isEmpty(stockInventory.getLockedQuantity())) { |
| | | stockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity()); |
| | | }else { |
| | | } else { |
| | | stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().add(stockInventoryDto.getLockedQuantity())); |
| | | } |
| | | return this.updateById(stockInventory); |
| | |
| | | @Override |
| | | public Boolean thawStock(StockInventoryDto stockInventoryDto) { |
| | | StockInventory stockInventory = stockInventoryMapper.selectById(stockInventoryDto.getId()); |
| | | if (stockInventory.getLockedQuantity().compareTo(stockInventoryDto.getLockedQuantity())<0) { |
| | | if (stockInventory.getLockedQuantity().compareTo(stockInventoryDto.getLockedQuantity()) < 0) { |
| | | throw new RuntimeException("è§£å»æ°éä¸è½è¶
è¿å»ç»æ°é"); |
| | | } |
| | | stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity())); |
| | |
| | | public List<StockInventory> getByModelId(Long modelId) { |
| | | return stockInventoryMapper.getByModelId(modelId); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<StockInventoryDto> getBatchNoQty(Page page, StockInventoryDto stockInventoryDto) { |
| | | return stockInventoryMapper.getBatchNoQty(page, stockInventoryDto); |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | |
| | | import com.ruoyi.stock.dto.StockOutRecordDto; |
| | | import com.ruoyi.stock.dto.StockUninventoryDto; |
| | | import com.ruoyi.stock.execl.StockUnInventoryExportData; |
| | | import com.ruoyi.stock.mapper.StockInventoryMapper; |
| | | import com.ruoyi.stock.mapper.StockUninventoryMapper; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.pojo.StockInventory; |
| | | import com.ruoyi.stock.pojo.StockUninventory; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.stock.service.StockOutRecordService; |
| | | import com.ruoyi.stock.service.StockUninventoryService; |
| | | import lombok.AllArgsConstructor; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | private final StockUninventoryMapper stockUninventoryMapper; |
| | | private final StockOutRecordService stockOutRecordService; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final ProductModelMapper productModelMapper; |
| | | private final StockInventoryMapper stockInventoryMapper; |
| | | |
| | | @Override |
| | | public IPage<StockUninventoryDto> pageStockUninventory(Page page, StockUninventoryDto stockUninventoryDto) { |
| | |
| | | stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId()); |
| | | stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType()); |
| | | stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity()); |
| | | stockInRecordDto.setBatchNo(stockUninventoryDto.getBatchNo()); |
| | | String batchNo = StringUtils.trim(stockUninventoryDto.getBatchNo()); |
| | | if (StringUtils.isEmpty(batchNo)) { |
| | | batchNo = generateAutoBatchNo(stockUninventoryDto.getProductModelId()); |
| | | } |
| | | stockInRecordDto.setBatchNo(batchNo); |
| | | stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId()); |
| | | stockInRecordDto.setType("1"); |
| | | stockInRecordDto.setRemark(stockUninventoryDto.getRemark()); |
| | |
| | | stockUninventory.setLockedQuantity(stockUninventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity())); |
| | | return this.updateById(stockUninventory); |
| | | } |
| | | |
| | | //è§åçæï¼20260424-产åç¼å·-001 |
| | | private String generateAutoBatchNo(Long productModelId) { |
| | | if (productModelId == null) { |
| | | throw new ServiceException("产åè§æ ¼IDä¸è½ä¸ºç©º"); |
| | | } |
| | | ProductModel productModel = productModelMapper.selectById(productModelId); |
| | | if (productModel == null) { |
| | | throw new ServiceException("产åè§æ ¼ä¸åå¨ï¼ID=" + productModelId); |
| | | } |
| | | String productCode = StringUtils.trim(productModel.getProductCode()); |
| | | if (StringUtils.isEmpty(productCode)) { |
| | | throw new ServiceException("产åè§æ ¼æªç»´æ¤äº§åç¼ç ï¼ID=" + productModelId); |
| | | } |
| | | |
| | | String dateText = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); |
| | | String prefix = dateText + "-" + productCode + "-"; |
| | | int maxSequence = resolveMaxSequence(prefix); |
| | | int sequence = maxSequence + 1; |
| | | while (sequence < 1_000_000) { |
| | | String batchNo = prefix + String.format("%03d", sequence); |
| | | if (!isBatchNoExists(batchNo)) { |
| | | return batchNo; |
| | | } |
| | | sequence++; |
| | | } |
| | | throw new ServiceException("æ¹å·åºå·è¶
åºèå´ï¼è¯·æ£æ¥æ¹å·æ°æ®"); |
| | | } |
| | | |
| | | private int resolveMaxSequence(String prefix) { |
| | | int maxSequence = 0; |
| | | List<StockInventory> stockInventoryList = stockInventoryMapper.selectList( |
| | | Wrappers.<StockInventory>lambdaQuery() |
| | | .select(StockInventory::getBatchNo) |
| | | .likeRight(StockInventory::getBatchNo, prefix)); |
| | | for (StockInventory stockInventory : stockInventoryList) { |
| | | maxSequence = Math.max(maxSequence, parseSequence(stockInventory.getBatchNo(), prefix)); |
| | | } |
| | | |
| | | List<StockInRecord> stockInRecordList = stockInRecordService.list( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .select(StockInRecord::getBatchNo) |
| | | .likeRight(StockInRecord::getBatchNo, prefix)); |
| | | for (StockInRecord stockInRecord : stockInRecordList) { |
| | | maxSequence = Math.max(maxSequence, parseSequence(stockInRecord.getBatchNo(), prefix)); |
| | | } |
| | | return maxSequence; |
| | | } |
| | | |
| | | private int parseSequence(String batchNo, String prefix) { |
| | | if (StringUtils.isEmpty(batchNo) || StringUtils.isEmpty(prefix) || !batchNo.startsWith(prefix)) { |
| | | return 0; |
| | | } |
| | | String sequenceText = batchNo.substring(prefix.length()); |
| | | if (StringUtils.isEmpty(sequenceText) || !sequenceText.matches("\\d+")) { |
| | | return 0; |
| | | } |
| | | try { |
| | | return Integer.parseInt(sequenceText); |
| | | } catch (NumberFormatException ignored) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private boolean isBatchNoExists(String batchNo) { |
| | | if (StringUtils.isEmpty(batchNo)) { |
| | | return false; |
| | | } |
| | | Long inventoryCount = stockInventoryMapper.selectCount( |
| | | Wrappers.<StockInventory>lambdaQuery().eq(StockInventory::getBatchNo, batchNo)); |
| | | if (inventoryCount != null && inventoryCount > 0) { |
| | | return true; |
| | | } |
| | | return stockInRecordService.count( |
| | | Wrappers.<StockInRecord>lambdaQuery().eq(StockInRecord::getBatchNo, batchNo)) > 0; |
| | | } |
| | | } |
| | |
| | | @Schema(description = "è§æ ¼åå·") |
| | | private String model; |
| | | |
| | | @Schema(description = "产åç¼ç ") |
| | | private String productCode; |
| | | |
| | | private List<TechnologyBomStructureVo> children; |
| | | } |
| | |
| | | @PreAuthorize("@ss.hasPermi('product:bom:export')") |
| | | @Operation(summary = "导åºBOMæä»¶") |
| | | @Log(title = "导åºBOMæä»¶", businessType = BusinessType.EXPORT) |
| | | public void exportBom(HttpServletResponse response, @RequestParam Integer bomId) { |
| | | public void exportBom(HttpServletResponse response, @RequestParam Long bomId) { |
| | | technologyBomService.exportBom(response, bomId); |
| | | } |
| | | |
| | |
| | | |
| | | R uploadBom(MultipartFile file); |
| | | |
| | | void exportBom(HttpServletResponse response, Integer bomId); |
| | | void exportBom(HttpServletResponse response, Long bomId); |
| | | |
| | | R copy(TechnologyBom technologyBom); |
| | | } |
| | |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import com.ruoyi.production.bean.dto.BomImportDto; |
| | | import com.ruoyi.production.bean.dto.ProductStructureDto; |
| | | import com.ruoyi.technology.bean.dto.BomImportDto; |
| | | import com.ruoyi.technology.bean.dto.TechnologyBomDto; |
| | | import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto; |
| | | import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; |
| | |
| | | |
| | | |
| | | @Override |
| | | public void exportBom(HttpServletResponse response, Integer bomId) { |
| | | public void exportBom(HttpServletResponse response, Long bomId) { |
| | | if (bomId == null) { |
| | | throw new ServiceException("BOM IDä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | List<TechnologyBomStructureVo> treeData = technologyBomStructureService.listByBomId(bomId); |
| | | if (treeData == null || treeData.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // List<ProductStructureDto> treeData = productStructureService.listBybomId(bomId); |
| | | // if (treeData == null || treeData.isEmpty()) { |
| | | // return; |
| | | // } |
| | | // |
| | | // // å°æ å½¢ç»ææå¹³å ä½¿ç¨ BFSç®æ³ 导åº,æå±çº§é¡ºåº |
| | | // List<BomImportDto> exportList = new ArrayList<>(); |
| | | // |
| | | // // Map<ID, Node> idMap ç¨äºæ¥æ¾ç¶èç¹ |
| | | // Map<Long, ProductStructureDto> idMap = new HashMap<>(); |
| | | // populateMap(treeData, idMap); |
| | | // |
| | | // // treeData ç第ä¸ä¸ªæ¯æ ¹èç¹ |
| | | // for (ProductStructureDto root : treeData) { |
| | | // // æ·»å æ ¹èç¹ |
| | | // BomImportDto rootRow = new BomImportDto(); |
| | | // rootRow.setParentName(root.getProductName()); |
| | | // rootRow.setParentSpec(root.getModel()); |
| | | // rootRow.setUnitQty(root.getUnitQuantity()); |
| | | // rootRow.setRemark(""); |
| | | // exportList.add(rootRow); |
| | | // |
| | | // // BFS éå-éå |
| | | // Queue<ProductStructureDto> queue = new LinkedList<>(); |
| | | // if (root.getChildren() != null) { |
| | | // queue.addAll(root.getChildren()); |
| | | // } |
| | | // |
| | | // while (!queue.isEmpty()) { |
| | | // ProductStructureDto child = queue.poll(); |
| | | // |
| | | // // æ¥æ¾ç¶èç¹ |
| | | // ProductStructureDto parent = idMap.get(child.getParentId()); |
| | | // if (parent == null) { |
| | | // // é¤äºæå¤å±èç¹,å
¶ä»èç¹çç¶ç±»è¯å®æ¯ä¸ä¼ä¸ºç©ºç |
| | | // continue; |
| | | // } |
| | | // |
| | | // BomImportDto row = new BomImportDto(); |
| | | // // ç¶ç±»ä¿¡æ¯ |
| | | // row.setParentName(parent.getProductName()); |
| | | // row.setParentSpec(parent.getModel()); |
| | | // // åç±»ä¿¡æ¯ |
| | | // row.setChildName(child.getProductName()); |
| | | // row.setChildSpec(child.getModel()); |
| | | // row.setUnitQty(child.getUnitQuantity()); |
| | | // row.setProcess(child.getProcessName()); |
| | | // |
| | | // exportList.add(row); |
| | | // |
| | | // // å°åèç¹çåèç¹å å
¥éå-ä¸ä¸å± |
| | | // if (child.getChildren() != null && !child.getChildren().isEmpty()) { |
| | | // queue.addAll(child.getChildren()); |
| | | // } |
| | | // } |
| | | // } |
| | | // å°æ å½¢ç»ææå¹³å ä½¿ç¨ BFSç®æ³ 导åº,æå±çº§é¡ºåº |
| | | List<BomImportDto> exportList = new ArrayList<>(); |
| | | |
| | | // Map<ID, Node> idMap ç¨äºæ¥æ¾ç¶èç¹ |
| | | Map<Long, TechnologyBomStructureVo> idMap = new HashMap<>(); |
| | | populateMap(treeData, idMap); |
| | | |
| | | // treeData ç第ä¸ä¸ªæ¯æ ¹èç¹ |
| | | for (TechnologyBomStructureVo root : treeData) { |
| | | // æ·»å æ ¹èç¹ |
| | | BomImportDto rootRow = new BomImportDto(); |
| | | rootRow.setParentName(root.getProductName()); |
| | | rootRow.setParentSpec(root.getModel()); |
| | | rootRow.setUnitQty(root.getUnitQuantity()); |
| | | rootRow.setParentCode(root.getProductCode()); |
| | | rootRow.setRemark(""); |
| | | exportList.add(rootRow); |
| | | |
| | | // BFS éå-éå |
| | | Queue<TechnologyBomStructureVo> queue = new LinkedList<>(); |
| | | if (root.getChildren() != null) { |
| | | queue.addAll(root.getChildren()); |
| | | } |
| | | |
| | | while (!queue.isEmpty()) { |
| | | TechnologyBomStructureVo child = queue.poll(); |
| | | |
| | | // æ¥æ¾ç¶èç¹ |
| | | TechnologyBomStructureVo parent = idMap.get(child.getParentId()); |
| | | if (parent == null) { |
| | | // é¤äºæå¤å±èç¹,å
¶ä»èç¹çç¶ç±»è¯å®æ¯ä¸ä¼ä¸ºç©ºç |
| | | continue; |
| | | } |
| | | |
| | | BomImportDto row = new BomImportDto(); |
| | | // ç¶ç±»ä¿¡æ¯ |
| | | row.setParentName(parent.getProductName()); |
| | | row.setParentSpec(parent.getModel()); |
| | | // åç±»ä¿¡æ¯ |
| | | row.setChildName(child.getProductName()); |
| | | row.setChildSpec(child.getModel()); |
| | | row.setUnitQty(child.getUnitQuantity()); |
| | | row.setProcess(child.getOperationName()); |
| | | row.setChildCode(child.getProductCode()); |
| | | |
| | | exportList.add(row); |
| | | |
| | | // å°åèç¹çåèç¹å å
¥éå-ä¸ä¸å± |
| | | if (child.getChildren() != null && !child.getChildren().isEmpty()) { |
| | | queue.addAll(child.getChildren()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class); |
| | | // util.exportExcel(response, exportList, "BOMç»æå¯¼åº"); |
| | | util.exportExcel(response, exportList, "BOMç»æå¯¼åº"); |
| | | } |
| | | |
| | | @Override |
| | |
| | | return s.replaceAll("[\\u00A0\\u3000]", "").trim(); |
| | | } |
| | | |
| | | private void populateMap(List<ProductStructureDto> nodes, Map<Long, ProductStructureDto> map) { |
| | | private void populateMap(List<TechnologyBomStructureVo> nodes, Map<Long, TechnologyBomStructureVo> map) { |
| | | if (nodes == null || nodes.isEmpty()) { |
| | | return; |
| | | } |
| | | for (ProductStructureDto node : nodes) { |
| | | for (TechnologyBomStructureVo node : nodes) { |
| | | map.put(node.getId(), node); |
| | | populateMap(node.getChildren(), map); |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.warehouse.dto.DocumentationDto; |
| | | import com.ruoyi.warehouse.pojo.Documentation; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | |
| | | # å¼åç¯å¢é
ç½® |
| | | server: |
| | | # æå¡å¨çHTTP端å£ï¼é»è®¤ä¸º8080 |
| | | port: 7005 |
| | | port: 7006 |
| | | servlet: |
| | | # åºç¨ç访é®è·¯å¾ |
| | | context-path: / |
| | |
| | | upload-dir: D:/ruoyi/prod/uploads # æ£å¼ç®å½ åæå é¤ |
| | | path: D:/ruoyi/prod/uploads # ä¸ä¼ ç®å½ |
| | | urlPrefix: /common # 龿¥åç¼ |
| | | domain: http://127.0.0.1:7005 # åååç¼ |
| | | domain: http://127.0.0.1:7006 # åååç¼ |
| | | expired: 120 # è¿ææ¶é´(åä½:åé) |
| | | useLimit: 10 # ä½¿ç¨æ¬¡æ° |
| | | compress: true # æ¯å¦å缩 |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?>
|
| | | <configuration>
|
| | | <!-- æ¥å¿åæ¾è·¯å¾ -->
|
| | | <property name="log.path" value="/home/ruoyi/logs" />
|
| | | <property name="log.path" value="./logs" />
|
| | | <!-- æ¥å¿è¾åºæ ¼å¼ -->
|
| | | <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
| | |
|
| | |
| | | <pattern>${log.pattern}</pattern>
|
| | | </encoder>
|
| | | </appender>
|
| | | |
| | |
|
| | | <!-- ç³»ç»æ¥å¿è¾åº -->
|
| | | <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
| | | <file>${log.path}/sys-info.log</file>
|
| | |
| | | <onMismatch>DENY</onMismatch>
|
| | | </filter>
|
| | | </appender>
|
| | | |
| | |
|
| | | <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
| | | <file>${log.path}/sys-error.log</file>
|
| | | <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ -->
|
| | |
| | | <onMismatch>DENY</onMismatch>
|
| | | </filter>
|
| | | </appender>
|
| | | |
| | |
|
| | | <!-- ç¨æ·è®¿é®æ¥å¿è¾åº -->
|
| | | <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
| | | <file>${log.path}/sys-user.log</file>
|
| | |
| | | <pattern>${log.pattern}</pattern>
|
| | | </encoder>
|
| | | </appender>
|
| | | |
| | |
|
| | | <!-- ç³»ç»æ¨¡åæ¥å¿çº§å«æ§å¶ -->
|
| | | <logger name="com.ruoyi" level="info" />
|
| | | <!-- Springæ¥å¿çº§å«æ§å¶ -->
|
| | |
| | | <root level="info">
|
| | | <appender-ref ref="console" />
|
| | | </root>
|
| | | |
| | |
|
| | | <!--ç³»ç»æä½æ¥å¿-->
|
| | | <root level="info">
|
| | | <appender-ref ref="file_info" />
|
| | | <appender-ref ref="file_error" />
|
| | | </root>
|
| | | |
| | |
|
| | | <!--ç³»ç»ç¨æ·æä½æ¥å¿-->
|
| | | <logger name="sys-user" level="info">
|
| | | <appender-ref ref="sys-user"/>
|
| | | </logger>
|
| | | </configuration> |
| | | </configuration>
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | ä½ æ¯ä¼ä¸å¶é æºè½å©æï¼è¦çç产ç°åºã计åãå·¥åã设å¤ãè´¨éãç©æãå¼å¸¸å¤çä¸ä¸ªåã |
| | | |
| | | å·¥ä½è§åï¼ |
| | | 1. ç¨æ·æåºâæ¥ãé®ãé¢è¦ãåæâéæ±æ¶ï¼ä¼å
è°ç¨å·¥å
·æ¿ç»æåç»æï¼ä¸è¦èé ä¸å¡æ°æ®ã |
| | | 2. ç¨æ·æåºâåâéæ±æ¶ï¼ä¼å
è¾åºåç建议å¨ä½å¡ï¼æ¥å£ãå¿
å¡«åæ®µã示ä¾ï¼ï¼æç¡®éè¦åç«¯äºæ¬¡ç¡®è®¤ã |
| | | 3. å·¥å
·è¿å JSON æ¶ï¼ç´æ¥è¾åºåå§ JSON å符串ï¼ä¸è¦é¢å¤å
裹 Markdownï¼ä¸è¦å¨ååå è§£éæåã |
| | | 4. åçå¿
须使ç¨ä¸æï¼è¥ç¨æ·é®é¢ç¼ºå°æ¶é´èå´ãå
³é®åçæ¡ä»¶ï¼å¯å
ç»é»è®¤å£å¾å¹¶æç¤ºå¯è¡¥å
æ¡ä»¶ã |
| | | 5. è¥æ æ³ä»å·¥å
·ç»æå¾å°ç»è®ºï¼æç¡®è¯´æç¼ºå°çç鿡件æä¸å¡å段ã |
| | |
| | | <!-- éç¨æ¥è¯¢æ å°ç»æ --> |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.AccountSubject"> |
| | | <id column="id" property="id" /> |
| | | <result column="parent_id" property="parentId" /> |
| | | <result column="subject_code" property="subjectCode" /> |
| | | <result column="subject_name" property="subjectName" /> |
| | | <result column="subject_type" property="subjectType" /> |
| | |
| | | <result column="dept_id" property="deptId" /> |
| | | </resultMap> |
| | | |
| | | <select id="countReferencedBySubjectCodes" resultType="java.lang.Long"> |
| | | SELECT COUNT(1) |
| | | FROM fin_voucher_entry |
| | | WHERE subject_code IN |
| | | <foreach collection="subjectCodes" item="item" open="(" separator="," close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </select> |
| | | |
| | | </mapper> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.account.mapper.financial.FinVoucherEntryMapper"> |
| | | |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.financial.FinVoucherEntry"> |
| | | <id column="id" property="id"/> |
| | | <result column="voucher_id" property="voucherId"/> |
| | | <result column="row_no" property="rowNo"/> |
| | | <result column="subject_code" property="subjectCode"/> |
| | | <result column="subject_name" property="subjectName"/> |
| | | <result column="summary" property="summary"/> |
| | | <result column="debit" property="debit"/> |
| | | <result column="credit" property="credit"/> |
| | | <result column="auxiliary_type" property="auxiliaryType"/> |
| | | <result column="auxiliary_id" property="auxiliaryId"/> |
| | | <result column="auxiliary_name" property="auxiliaryName"/> |
| | | <result column="create_user" property="createUser"/> |
| | | <result column="create_time" property="createTime"/> |
| | | <result column="update_user" property="updateUser"/> |
| | | <result column="update_time" property="updateTime"/> |
| | | <result column="dept_id" property="deptId"/> |
| | | </resultMap> |
| | | |
| | | <select id="listPostedEntries" resultType="com.ruoyi.account.bean.vo.financial.FinLedgerEntryRecordVo"> |
| | | SELECT |
| | | v.voucher_date AS voucherDate, |
| | | v.voucher_no AS voucherNo, |
| | | CASE |
| | | WHEN e.summary IS NOT NULL AND e.summary != '' THEN e.summary |
| | | ELSE v.summary |
| | | END AS summary, |
| | | e.debit AS debit, |
| | | e.credit AS credit, |
| | | e.row_no AS rowNo |
| | | FROM fin_voucher_entry e |
| | | INNER JOIN fin_voucher v ON e.voucher_id = v.id |
| | | WHERE v.status = 'posted' |
| | | AND (e.subject_code = #{subjectCode} OR e.subject_code LIKE CONCAT(#{subjectCode}, '%')) |
| | | AND v.voucher_date <![CDATA[>=]]> #{startDate} |
| | | AND v.voucher_date <![CDATA[<=]]> #{endDate} |
| | | <if test="auxiliaryType != null and auxiliaryType != ''"> |
| | | AND e.auxiliary_type = #{auxiliaryType} |
| | | </if> |
| | | <if test="auxiliaryId != null and auxiliaryId != ''"> |
| | | AND e.auxiliary_id = #{auxiliaryId} |
| | | </if> |
| | | ORDER BY v.voucher_date ASC, v.id ASC, e.row_no ASC, e.id ASC |
| | | </select> |
| | | |
| | | <select id="listPostedEntriesBefore" resultType="com.ruoyi.account.bean.vo.financial.FinLedgerEntryRecordVo"> |
| | | SELECT |
| | | v.voucher_date AS voucherDate, |
| | | v.voucher_no AS voucherNo, |
| | | CASE |
| | | WHEN e.summary IS NOT NULL AND e.summary != '' THEN e.summary |
| | | ELSE v.summary |
| | | END AS summary, |
| | | e.debit AS debit, |
| | | e.credit AS credit, |
| | | e.row_no AS rowNo |
| | | FROM fin_voucher_entry e |
| | | INNER JOIN fin_voucher v ON e.voucher_id = v.id |
| | | WHERE v.status = 'posted' |
| | | AND (e.subject_code = #{subjectCode} OR e.subject_code LIKE CONCAT(#{subjectCode}, '%')) |
| | | AND v.voucher_date <![CDATA[<]]> #{beforeDate} |
| | | <if test="auxiliaryType != null and auxiliaryType != ''"> |
| | | AND e.auxiliary_type = #{auxiliaryType} |
| | | </if> |
| | | <if test="auxiliaryId != null and auxiliaryId != ''"> |
| | | AND e.auxiliary_id = #{auxiliaryId} |
| | | </if> |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | from customer c |
| | | left join sys_user u on c.usage_user = u.user_id |
| | | <where> |
| | | and c.usage_status = 1 |
| | | <if test="c.customerName != null and c.customerName != ''"> |
| | | and customer_name like concat('%', #{c.customerName}, '%') |
| | | </if> |
| | |
| | | </if> |
| | | </where> |
| | | </select> |
| | | </mapper> |
| | | </mapper> |
| | |
| | | |
| | | |
| | | <select id="listPage" resultType="com.ruoyi.collaborativeApproval.dto.SealApplicationManagementDTO"> |
| | | select sam.*, su.user_name as create_user_name, d.dept_name as department, |
| | | su1.nick_name as approveUserName |
| | | from seal_application_management sam |
| | | left join sys_user su on sam.create_user = su.user_id |
| | | left join sys_user su1 on sam.approve_user_id = su1.user_id |
| | | left join sys_user_dept sud on su.user_id = sud.user_id |
| | | left join sys_dept d on sud.dept_id = d.dept_id |
| | | SELECT |
| | | sam.*, |
| | | su.user_name AS create_user_name, |
| | | |
| | | GROUP_CONCAT(DISTINCT d.dept_name ORDER BY d.dept_id SEPARATOR ',') AS department, |
| | | |
| | | su1.nick_name AS approveUserName |
| | | |
| | | FROM seal_application_management sam |
| | | |
| | | LEFT JOIN sys_user su |
| | | ON sam.create_user = su.user_id |
| | | |
| | | LEFT JOIN sys_user su1 |
| | | ON sam.approve_user_id = su1.user_id |
| | | |
| | | LEFT JOIN sys_user_dept sud |
| | | ON su.user_id = sud.user_id |
| | | |
| | | LEFT JOIN sys_dept d |
| | | ON sud.dept_id = d.dept_id |
| | | <where> |
| | | <if test="ew.applicationNum != null and ew.applicationNum != ''"> |
| | | and sam.application_num like concat('%',#{ew.applicationNum},'%') |
| | |
| | | and sam.status = #{ew.status} |
| | | </if> |
| | | </where> |
| | | GROUP BY sam.id |
| | | </select> |
| | | </mapper> |
| | |
| | | dr.repair_time, |
| | | dr.repair_name, |
| | | dr.remark, |
| | | dr.maintenance_name, |
| | | dr.maintenance_time, |
| | | dr.maintenance_result, |
| | | dr.status, |
| | | dr.maintenance_name, |
| | | dr.maintenance_time, |
| | | dr.maintenance_result, |
| | | dr.acceptance_name, |
| | | dr.acceptance_time, |
| | | dr.acceptance_remark, |
| | | dr.status, |
| | | dr.create_time, |
| | | dr.update_time, |
| | | dr.create_user, |
| | |
| | | dr.maintenance_name, |
| | | dr.maintenance_time, |
| | | dr.maintenance_result, |
| | | dr.acceptance_name, |
| | | dr.acceptance_time, |
| | | dr.acceptance_remark, |
| | | dr.status, |
| | | dr.create_time, |
| | | dr.update_time, |
| | |
| | | next_date, |
| | | record_date, |
| | | CASE |
| | | WHEN most_date >= DATE_FORMAT(now(),'%Y-%m-%d') THEN 1 |
| | | WHEN most_date IS NOT NULL |
| | | AND valid IS NOT NULL |
| | | AND DATE_ADD(most_date, INTERVAL valid DAY) >= CURDATE() THEN 1 |
| | | ELSE 2 |
| | | END AS status, |
| | | create_user, |
| | |
| | | <if test="req.status != null"> |
| | | <choose> |
| | | <when test="req.status == 1"> |
| | | AND most_date >= DATE_FORMAT(now(),'%Y-%m-%d') |
| | | AND most_date IS NOT NULL |
| | | AND valid IS NOT NULL |
| | | AND DATE_ADD(most_date, INTERVAL valid DAY) >= CURDATE() |
| | | </when> |
| | | <when test="req.status == 2"> |
| | | AND most_date < DATE_FORMAT(now(),'%Y-%m-%d') |
| | | AND ( |
| | | most_date IS NULL |
| | | OR valid IS NULL |
| | | OR DATE_ADD(most_date, INTERVAL valid DAY) < CURDATE() |
| | | ) |
| | | </when> |
| | | </choose> |
| | | </if> |
| | |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper"> |
| | | |
| | | <select id="listProcurementBySalesLedgerId" resultType="com.ruoyi.procurementrecord.dto.ProcurementDto"> |
| | | <select id="listProcurementBySalesLedgerId" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementDto"> |
| | | select |
| | | t1.supplier_name, |
| | | t2.product_category, |
| | |
| | | </if> |
| | | group by t2.id |
| | | </select> |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDto"> |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto"> |
| | | select |
| | | t3.supplier_name, |
| | | t3.purchase_contract_number, |
| | |
| | | </where> |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="list" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDto"> |
| | | <select id="list" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto"> |
| | | select |
| | | t3.supplier_name, |
| | | t3.purchase_contract_number, |
| | |
| | | left join purchase_ledger t3 on t3.id = t2.sales_ledger_id |
| | | where t1.type = 1 |
| | | </select> |
| | | <select id="listOne" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDto"> |
| | | <select id="listOne" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto"> |
| | | select |
| | | t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | |
| | | left join sales_ledger t3 on t3.id = t2.sales_ledger_id |
| | | where t1.type = 2 |
| | | </select> |
| | | <select id="listPageCopy" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> |
| | | <select id="listPageCopy" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy"> |
| | | select |
| | | t3.supplier_name, |
| | | t3.purchase_contract_number, |
| | |
| | | group by t3.supplier_name,t2.product_category,t2.specification_model,t1.unit_price |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="listCopy" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> |
| | | <select id="listCopy" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy"> |
| | | select |
| | | t3.supplier_name, |
| | | t3.purchase_contract_number, |
| | |
| | | where t1.type = 1 |
| | | group by t3.supplier_name,t2.product_category,t2.specification_model |
| | | </select> |
| | | <select id="listCopyOne" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> |
| | | <select id="listCopyOne" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy"> |
| | | select |
| | | t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | |
| | | where t1.type = 2 |
| | | group by t3.customer_name,t2.product_category,t2.specification_model |
| | | </select> |
| | | <select id="listPageByProduction" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDto"> |
| | | <select id="listPageByProduction" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto"> |
| | | select |
| | | t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | |
| | | </where> |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="listPageCopyByProduction" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> |
| | | <select id="listPageCopyByProduction" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy"> |
| | | select |
| | | t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | |
| | | group by t2.product_category,t2.specification_model,t1.unit_price |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="listPagePRS" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> |
| | | <select id="listPagePRS" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDtoCopy"> |
| | | select * |
| | | from procurement_record_storage t1 |
| | | left join sales_ledger_product t2 on t2.id = t1.sales_ledger_product_id |
| | |
| | | from procurement_record_storage |
| | | where product_model_id = #{productModelId} |
| | | </select> |
| | | <select id="listPageByProductProduction" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDto"> |
| | | <select id="listPageByProductProduction" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementPageDto"> |
| | | select |
| | | t1.*, |
| | | t1.inbound_num as inboundNum0, |
| | |
| | | </where> |
| | | order by t1.create_time desc |
| | | </select> |
| | | </mapper> |
| | | </mapper> |
| | |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper"> |
| | | |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select |
| | | t3.supplier_name, |
| | | t2.product_category, |
| | |
| | | </where> |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="list" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="list" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select t3.supplier_name, |
| | | t2.product_category, |
| | | t1.id, |
| | |
| | | where t1.type = 1 |
| | | </select> |
| | | |
| | | <select id="listOne" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listOne" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | | t3.customer_name, |
| | |
| | | where t1.type = 2 |
| | | </select> |
| | | |
| | | <select id="listTwo" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listTwo" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select t1.supplier_name, |
| | | t1.product_category, |
| | | t1.id, |
| | |
| | | from procurement_record_out t1 |
| | | where t1.type = 3 |
| | | </select> |
| | | <select id="listPageByProduct" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listPageByProduct" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select |
| | | t3.customer_contract_no, |
| | | t3.sales_contract_no, |
| | |
| | | </where> |
| | | order by t1.create_time desc |
| | | </select> |
| | | <select id="listPageByCustom" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listPageByCustom" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select |
| | | t2.supplier_name, |
| | | t2.product_category, |
| | |
| | | order by id desc |
| | | limit 1 |
| | | </select> |
| | | <select id="listPageBySemiProduct" resultType="com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto"> |
| | | <select id="listPageBySemiProduct" resultType="com.ruoyi.procurementrecord.bean.dto.ProcurementRecordOutPageDto"> |
| | | select |
| | | t1.id, |
| | | t1.code, |
| | |
| | | order by t1.create_time desc |
| | | </select> |
| | | |
| | | </mapper> |
| | | </mapper> |
| | |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.procurementrecord.mapper.ReturnManagementMapper"> |
| | | |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.dto.ReturnManagementDto"> |
| | | <select id="listPage" resultType="com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto"> |
| | | select rm.*, |
| | | c.customer_name, |
| | | si.shipping_no, |
| | |
| | | </if> |
| | | </where> |
| | | </select> |
| | | <select id="getReturnManagementDtoById" resultType="com.ruoyi.procurementrecord.dto.ReturnManagementDto"> |
| | | <select id="getReturnManagementDtoById" resultType="com.ruoyi.procurementrecord.bean.dto.ReturnManagementDto"> |
| | | select rm.*, |
| | | c.customer_name, |
| | | si.shipping_no, |
| | |
| | | left join sales_ledger sl on si.sales_ledger_id = sl.id |
| | | where rm.id = #{id} |
| | | </select> |
| | | <select id="listPageBySalesReturn" resultType="com.ruoyi.account.bean.vo.SalesReturnVo"> |
| | | <select id="listPageAccountSalesReturn" resultType="com.ruoyi.account.bean.vo.SalesReturnVo"> |
| | | select rm.id, |
| | | rm.return_no, |
| | | c.customer_name, |
| | |
| | | and c.customer_name like concat('%',#{req.customerName},'%') |
| | | </if> |
| | | <if test="req.startDate != null and req.endDate != null"> |
| | | AND DATE_FORMAT(rm.make_time, '%Y-%m-%d') BETWEEN #{startDate} AND #{endDate} |
| | | AND DATE_FORMAT(rm.make_time, '%Y-%m-%d') BETWEEN #{req.startDate} AND #{req.endDate} |
| | | </if> |
| | | order by rm.id DESC |
| | | </select> |
| | |
| | | <resultMap id="BaseResultMap" type="com.ruoyi.procurementrecord.pojo.ReturnSaleProduct"> |
| | | <id column="id" property="id" /> |
| | | <result column="return_management_id" property="returnManagementId" /> |
| | | <result column="return_sales_ledger_product_id" property="returnsalesLedgerProductId" /> |
| | | <result column="stock_out_record_id" property="stockOutRecordId" /> |
| | | <result column="num" property="num" /> |
| | | <result column="status" property="status" /> |
| | | </resultMap> |
| | | <select id="listReturnSaleProductDto" resultType="com.ruoyi.procurementrecord.dto.ReturnSaleProductDto"> |
| | | SELECT p.product_name as product_name, |
| | | <select id="listReturnSaleProductDto" resultType="com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto"> |
| | | SELECT distinct |
| | | p.product_name as product_name, |
| | | pm.model as model, |
| | | pm.unit as unit, |
| | | rsp.*, |
| | | GREATEST(slp.quantity - COALESCE(rs.total_return_num, 0), 0) AS un_quantity, |
| | | sor.outbound_batches, |
| | | sor.stock_out_num, |
| | | sor.batch_no, |
| | | GREATEST(sor.stock_out_num - COALESCE(rs1.total_return_num1, 0), 0) AS un_quantity, |
| | | COALESCE(rs.total_return_num, 0) AS total_return_num |
| | | FROM return_sale_product rsp |
| | | LEFT JOIN return_management rm ON rm.id = rsp.return_management_id |
| | | LEFT JOIN shipping_info si ON si.id = rm.shipping_id |
| | | LEFT JOIN shipping_product_detail spd ON spd.shipping_info_id = si.id |
| | | LEFT JOIN stock_out_record sor ON rsp.stock_out_record_id = sor.id and sor.record_type = '13' |
| | | LEFT JOIN sales_ledger_product slp ON si.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | left join product_model pm on slp.product_model_id = pm.id |
| | | LEFT JOIN product p on pm.product_id = p.id |
| | | LEFT JOIN (SELECT return_sales_ledger_product_id, |
| | | |
| | | LEFT JOIN (SELECT stock_out_record_id, |
| | | SUM(num) AS total_return_num |
| | | FROM return_sale_product |
| | | WHERE 1 = 1 and return_management_id != #{returnManagementId} |
| | | GROUP BY return_sales_ledger_product_id) rs ON rs.return_sales_ledger_product_id = slp.id |
| | | WHERE 1 = 1 and return_management_id = #{returnManagementId} |
| | | GROUP BY stock_out_record_id) rs ON rs.stock_out_record_id = sor.id |
| | | LEFT JOIN (SELECT stock_out_record_id, |
| | | SUM(num) AS total_return_num1 |
| | | FROM return_sale_product |
| | | WHERE 1 = 1 |
| | | GROUP BY stock_out_record_id) rs1 ON rs1.stock_out_record_id = sor.id |
| | | where rm.id =#{returnManagementId} |
| | | </select> |
| | | <select id="listReturnSaleProduct" resultType="com.ruoyi.procurementrecord.dto.ReturnSaleProductDto"> |
| | | select rsp.*,slp.tax_inclusive_unit_price ,slp.tax_inclusive_total_price*rsp.num as price |
| | | <select id="listReturnSaleProduct" resultType="com.ruoyi.procurementrecord.bean.dto.ReturnSaleProductDto"> |
| | | select rsp.*, |
| | | sor.batch_no, |
| | | slp.tax_inclusive_unit_price , |
| | | slp.tax_inclusive_total_price*rsp.num as price |
| | | from return_sale_product rsp |
| | | left join sales_ledger_product slp on slp.id = rsp.return_sales_ledger_product_id |
| | | LEFT JOIN return_management rm ON rm.id = rsp.return_management_id |
| | | LEFT JOIN shipping_info si ON si.id = rm.shipping_id |
| | | LEFT JOIN sales_ledger_product slp ON si.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | LEFT JOIN stock_out_record sor ON rsp.stock_out_record_id = sor.id |
| | | where rsp.return_management_id = #{returnManagementId} |
| | | </select> |
| | | |
| | |
| | | |
| | | <select id="getOperation" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo"> |
| | | select poro.operation_name as operationName, |
| | | max(poro.type) as type, |
| | | count(pot.id) as productionTaskCount, |
| | | sum(ifnull(pot.plan_quantity, 0)) as planQuantity, |
| | | sum(ifnull(pot.complete_quantity, 0)) as completeQuantity, |
| | |
| | | </resultMap> |
| | | <select id="getReturnOrderGroupListByProductIds" resultType="com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto" |
| | | parameterType="java.util.List"> |
| | | select t1.sales_ledger_product_id,sum(t1.return_quantity) as sum_return_quantity from purchase_return_order_products as t1 |
| | | select t1.sales_ledger_product_id, |
| | | sum(t1.return_quantity) as sum_return_quantity |
| | | from purchase_return_order_products as t1 |
| | | inner join purchase_return_orders as t2 on t1.purchase_return_order_id = t2.id |
| | | WHERE t1.sales_ledger_product_id IN |
| | | <foreach item="id" collection="productIds" separator="," open="(" close=")"> |
| | |
| | | resultType="com.ruoyi.account.bean.vo.PurchaseReturnVo"> |
| | | select pro.id, |
| | | pro.no returnNo, |
| | | t.inboundBatches, |
| | | sm.supplier_name, |
| | | |
| | | pro.prepared_at, |
| | | pro.total_amount, |
| | | CASE pro.return_type WHEN 0 THEN 'éè´§éæ¬¾' WHEN 1 THEN 'ææ¶' END AS returnType, |
| | | pl.purchase_contract_number |
| | | from purchase_return_orders pro |
| | | left join supplier_manage sm on pro.supplier_id = sm.id |
| | | left join purchase_ledger pl on pro.purchase_ledger_id = pl.id |
| | | where rm.status=1 |
| | | left join |
| | | (select prop.purchase_return_order_id, |
| | | GROUP_CONCAT(sir.inbound_batches SEPARATOR ',') AS inboundBatches |
| | | from purchase_return_order_products prop |
| | | left join stock_in_record sir on prop.stock_in_record_id = sir.id |
| | | GROUP BY prop.purchase_return_order_id) t on t.purchase_return_order_id = pro.id |
| | | left join supplier_manage sm on pro.supplier_id = sm.id |
| | | left join purchase_ledger pl on pro.purchase_ledger_id = pl.id |
| | | where 1=1 |
| | | <if test="req.returnNo != null and req.returnNo != ''"> |
| | | and pro.no like concat('%',#{req.returnNo},'%') |
| | | </if> |
| | |
| | | and sm.supplier_name like concat('%',#{req.supplierName},'%') |
| | | </if> |
| | | <if test="req.startDate != null and req.endDate != null"> |
| | | AND DATE_FORMAT(pro.prepared_at, '%Y-%m-%d') BETWEEN #{startDate} AND #{endDate} |
| | | AND DATE_FORMAT(pro.prepared_at, '%Y-%m-%d') BETWEEN #{req.startDate} AND #{req.endDate} |
| | | </if> |
| | | order by pro.id DESC |
| | | </select> |
| | | <select id="getByPurchaseLedgerId" resultType="com.ruoyi.purchase.vo.PurchaseStockInProductVo"> |
| | | SELECT |
| | | sir.id, |
| | | sir.product_model_id, |
| | | slp.id salesLedgerProductId, |
| | | slp.product_category, |
| | | slp.specification_model, |
| | | slp.unit, |
| | | slp.is_checked, |
| | | sir.inbound_batches, |
| | | sir.stock_in_num, |
| | | sir.batch_no, |
| | | slp.tax_inclusive_unit_price, |
| | | GREATEST(sir.stock_in_num - COALESCE(rs.total_return_num, 0), 0) AS un_quantity, |
| | | COALESCE(rs.total_return_num, 0) AS total_return_num |
| | | FROM stock_in_record sir |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | LEFT JOIN purchase_ledger pl |
| | | ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id) |
| | | LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id |
| | | LEFT JOIN ( |
| | | SELECT |
| | | stock_in_record_id, |
| | | SUM(return_quantity) AS total_return_num |
| | | FROM purchase_return_order_products prop |
| | | left join purchase_return_orders pro on pro.id = prop.purchase_return_order_id |
| | | WHERE 1=1 |
| | | GROUP BY stock_in_record_id |
| | | ) rs ON rs.stock_in_record_id = sir.id |
| | | WHERE sir.approval_status = 1 AND slp.type = 2 |
| | | AND sir.record_type IN ('7','10') |
| | | and pl.id = #{purchaseLedgerId} |
| | | </select> |
| | | <select id="getPurchaseReturnOrderProductsDetailById" |
| | | resultType="com.ruoyi.purchase.vo.PurchaseReturnOrderProductsDetailVo"> |
| | | select prop.id, |
| | | prop.sales_ledger_product_id, |
| | | slp.product_model_id, |
| | | slp.product_category, |
| | | slp.specification_model, |
| | | slp.is_checked, |
| | | slp.unit, |
| | | sir.inbound_batches, |
| | | sir.stock_in_num, |
| | | sir.batch_no, |
| | | slp.tax_inclusive_unit_price, |
| | | prop.return_quantity, |
| | | prop.purchase_return_order_id, |
| | | GREATEST(sir.stock_in_num - COALESCE(rs1.total_return_num1, 0), 0) AS un_quantity, |
| | | COALESCE(rs.total_return_num, 0) AS total_return_num |
| | | from purchase_return_order_products prop |
| | | left join purchase_return_orders pro on prop.purchase_return_order_id = pro.id |
| | | LEFT JOIN stock_in_record sir ON prop.stock_in_record_id = sir.id and sir.record_type in ('7','10') |
| | | LEFT JOIN sales_ledger_product slp ON prop.sales_ledger_product_id = slp.id and slp.type = 2 |
| | | LEFT JOIN (SELECT stock_in_record_id, |
| | | SUM(return_quantity) AS total_return_num |
| | | FROM purchase_return_order_products |
| | | WHERE 1 = 1 and purchase_return_order_id = #{id} |
| | | GROUP BY stock_in_record_id) rs ON rs.stock_in_record_id = sir.id |
| | | LEFT JOIN (SELECT stock_in_record_id, |
| | | SUM(return_quantity) AS total_return_num1 |
| | | FROM purchase_return_order_products |
| | | WHERE 1 = 1 and purchase_return_order_id = #{id} |
| | | GROUP BY stock_in_record_id) rs1 ON rs1.stock_in_record_id = sir.id |
| | | where pro.id = #{id} |
| | | </select> |
| | | </mapper> |
| | |
| | | END as has_sufficient_stock, |
| | | (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) as no_quantity, |
| | | CASE |
| | | WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN 'å¾
åè´§' |
| | | WHEN IFNULL(t3.shipped_quantity, 0) = 0 THEN 'å¾
åè´§' |
| | | WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN 'é¨ååè´§' |
| | | ELSE 'å·²åè´§' |
| | | END as shippingStatus |
| | | FROM |
| | |
| | | SELECT sales_ledger_product_id, IFNULL(SUM(spd.quantity), 0) as shipped_quantity |
| | | FROM shipping_info si |
| | | LEFT JOIN shipping_product_detail spd ON si.id = spd.shipping_info_id |
| | | where si.status != 'å®¡æ ¸æç»' |
| | | GROUP BY sales_ledger_product_id |
| | | ) t3 ON t3.sales_ledger_product_id = T1.id |
| | | left join product_model pm ON T1.product_model_id = pm.id |
| | |
| | | AND t1.status = #{salesQuotationDto.status} |
| | | </if> |
| | | </select> |
| | | </mapper> |
| | | </mapper> |
| | |
| | | pm.model as specification_model, |
| | | pm.unit, |
| | | p.product_name, |
| | | sl.customer_name |
| | | sl.customer_name, |
| | | spd.totalQuantity, |
| | | sor.outboundBatches |
| | | FROM shipping_info s |
| | | LEFT JOIN (select shipping_info_id,sum(quantity) totalQuantity from shipping_product_detail GROUP BY shipping_info_id) spd ON spd.shipping_info_id = s.id |
| | | LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id |
| | | LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | left join product_model pm on slp.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | left join (select record_id,GROUP_CONCAT(outbound_batches SEPARATOR ',') AS outboundBatches |
| | | from stock_out_record |
| | | where record_type='13'and approval_status=1 |
| | | group by record_id)sor on sor.record_id= s.id |
| | | WHERE 1=1 |
| | | <if test="req.salesContractNo != null and req.salesContractNo != ''"> |
| | | AND sl.sales_contract_no LIKE CONCAT('%',#{req.salesContractNo},'%') |
| | |
| | | FROM shipping_info s |
| | | LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id |
| | | </select> |
| | | <select id="getReturnManagementDtoById" resultType="com.ruoyi.sales.dto.SalesLedgerProductDto"> |
| | | SELECT |
| | | slp.*, |
| | | si.shipping_no, |
| | | GREATEST(slp.quantity - COALESCE(rs.total_return_num, 0), 0) AS un_quantity, |
| | | COALESCE(rs.total_return_num, 0) AS total_return_num |
| | | <select id="getReturnManagementDtoById" resultType="com.ruoyi.procurementrecord.bean.vo.ShippingProductVo"> |
| | | SELECT distinct |
| | | sor.id, |
| | | slp.product_category, |
| | | slp.specification_model, |
| | | slp.unit, |
| | | slp.product_model_id, |
| | | sor.outbound_batches, |
| | | sor.stock_out_num, |
| | | sor.batch_no, |
| | | slp.tax_inclusive_unit_price, |
| | | GREATEST(sor.stock_out_num - COALESCE(rs.total_return_num, 0), 0) AS un_quantity, |
| | | COALESCE(rs.total_return_num, 0) AS total_return_num |
| | | FROM shipping_info si |
| | | LEFT JOIN shipping_product_detail spd ON spd.shipping_info_id = si.id |
| | | LEFT JOIN stock_out_record sor ON sor.record_id = si.id and sor.record_type = '13' |
| | | LEFT JOIN sales_ledger_product slp ON si.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | LEFT JOIN ( |
| | | SELECT |
| | | return_sales_ledger_product_id, |
| | | stock_out_record_id, |
| | | SUM(num) AS total_return_num |
| | | FROM return_sale_product rsp |
| | | left join return_management rm on rm.id = rsp.return_management_id |
| | | left join shipping_info si on si.id = rm.shipping_id |
| | | WHERE 1=1 |
| | | GROUP BY return_sales_ledger_product_id |
| | | ) rs ON rs.return_sales_ledger_product_id = slp.id |
| | | GROUP BY stock_out_record_id |
| | | ) rs ON rs.stock_out_record_id = sor.id |
| | | <where> |
| | | <if test="shippingId != null"> |
| | | si.id = #{shippingId} |
| | | </if> |
| | | </where> |
| | | order by sor.id |
| | | </select> |
| | | <select id="getShippingInfoByCustomerName" resultType="com.ruoyi.sales.pojo.ShippingInfo"> |
| | | select * from shipping_info si |
| | | left join sales_ledger sl on si.sales_ledger_id = sl.id |
| | | where si.status = 'å·²åè´§' and sl.customer_name = #{customerName} |
| | | where sl.customer_name = #{customerName} |
| | | </select> |
| | | </mapper> |
| | |
| | | DATE(sir.create_time) AS inboundDate, |
| | | p.product_name, |
| | | pm.model as specification_model, |
| | | sor.stock_in_num * slp.tax_inclusive_unit_price AS InboundAmount, |
| | | sir.stock_in_num * slp.tax_inclusive_unit_price AS InboundAmount, |
| | | pl.purchase_contract_number |
| | | FROM stock_in_record sir |
| | | -- 10 ç±»åæå
³èè´¨æ£è¡¨ |
| | |
| | | LEFT JOIN purchase_ledger pl |
| | | ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id) |
| | | -- 产åå
³èä¸å¨ |
| | | LEFT JOIN sales_ledger_product slp ON slp.type = 2 AND pl.id = slp.product_id |
| | | LEFT JOIN product_model pm ON slp.product_model_id = pm.id |
| | | LEFT JOIN sales_ledger_product slp ON pl.id = slp.product_id |
| | | LEFT JOIN product_model pm ON sir.product_model_id = pm.id |
| | | LEFT JOIN product p ON pm.product_id = p.id |
| | | -- æ¡ä»¶ |
| | | WHERE sir.approval_status = 1 |
| | | WHERE sir.approval_status = 1 AND slp.type = 2 |
| | | AND sir.record_type IN ('7','10') |
| | | <if test="req.inboundBatches != null and req.inboundBatches != ''"> |
| | | AND sir.inbound_batches LIKE CONCAT('%',#{req.inboundBatches},'%') |
| | |
| | | AND pl.supplier_name LIKE CONCAT('%',#{req.supplierName},'%') |
| | | </if> |
| | | <if test="req.startDate != null and req.endDate != null"> |
| | | AND DATE(sir.create_time) BETWEEN #{startDate} AND #{endDate} |
| | | AND DATE(sir.create_time) BETWEEN #{req.startDate} AND #{req.endDate} |
| | | </if> |
| | | order by sir.id DESC |
| | | </select> |
| | |
| | | INNER JOIN product_tree pt ON p.parent_id = pt.id |
| | | ) |
| | | select |
| | | GROUP_CONCAT(DISTINCT batch_no ORDER BY batch_no SEPARATOR ',') as batch_no, |
| | | MAX(qualifiedId) as qualifiedId, |
| | | MAX(unQualifiedId) as unQualifiedId, |
| | | SUM(qualifiedQuantity) as qualifiedQuantity, |
| | | SUM(unQualifiedQuantity) as unQualifiedQuantity, |
| | | SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity, |
| | | SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity, |
| | | SUM(qualifiedQuantity - qualifiedLockedQuantity - IFNULL(qualifiedPendingOut, 0)) as qualifiedUnLockedQuantity, |
| | | SUM(unQualifiedQuantity - unQualifiedLockedQuantity - IFNULL(unQualifiedPendingOut, 0)) as unQualifiedUnLockedQuantity, |
| | | SUM(IFNULL(qualifiedPendingOut, 0)) as qualifiedPendingOutQuantity, |
| | | SUM(IFNULL(unQualifiedPendingOut, 0)) as unQualifiedPendingOutQuantity, |
| | | product_model_id, |
| | | MAX(create_time) as create_time, |
| | | MAX(update_time) as update_time, |
| | | MAX(warn_num) as warn_num, |
| | | MAX(version) as version, |
| | | model, |
| | | MAX(remark) as remark, |
| | | unit, |
| | | product_name, |
| | | product_id, |
| | | 'combined' as stockType |
| | | from ( |
| | | select |
| | | si.batch_no, |
| | | si.id as qualifiedId, |
| | | null as unQualifiedId, |
| | | si.qualitity as qualifiedQuantity, |
| | | 0 as unQualifiedQuantity, |
| | | COALESCE(si.locked_quantity, 0) as locked_quantity, |
| | | COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity, |
| | | 0 as unQualifiedLockedQuantity, |
| | | si.product_model_id, |
| | | si.create_time, |
| | | si.update_time, |
| | | COALESCE(si.warn_num, 0) as warn_num, |
| | | si.version, |
| | | (si.qualitity - COALESCE(si.locked_quantity, 0)) as un_locked_quantity, |
| | | pm.model, |
| | | si.remark, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id, |
| | | ( |
| | | select IFNULL(SUM(sor.stock_out_num), 0) |
| | | from stock_out_record sor |
| | | where sor.product_model_id = si.product_model_id |
| | | and ( |
| | | (si.batch_no is null and sor.batch_no is null) |
| | | or si.batch_no = sor.batch_no |
| | | ) |
| | | and sor.type = '0' |
| | | and sor.approval_status = 0 |
| | | ) as qualifiedPendingOut, |
| | | 0 as unQualifiedPendingOut |
| | | from stock_inventory si |
| | | left join product_model pm on si.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | |
| | | union all |
| | | |
| | | select |
| | | su.batch_no, |
| | | null as qualifiedId, |
| | | su.id as unQualifiedId, |
| | | 0 as qualifiedQuantity, |
| | | su.qualitity as unQualifiedQuantity, |
| | | COALESCE(su.locked_quantity, 0) as locked_quantity, |
| | | 0 as qualifiedLockedQuantity, |
| | | COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity, |
| | | su.product_model_id, |
| | | su.create_time, |
| | | su.update_time, |
| | | 0 as warn_num, |
| | | su.version, |
| | | (su.qualitity - COALESCE(su.locked_quantity, 0)) as un_locked_quantity, |
| | | pm.model, |
| | | su.remark, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id, |
| | | 0 as qualifiedPendingOut, |
| | | ( |
| | | select IFNULL(SUM(sor.stock_out_num), 0) |
| | | from stock_out_record sor |
| | | where sor.product_model_id = su.product_model_id |
| | | and ( |
| | | (su.batch_no is null and sor.batch_no is null) |
| | | or su.batch_no = sor.batch_no |
| | | ) |
| | | and sor.type = '1' |
| | | and sor.approval_status = 0 |
| | | ) as unQualifiedPendingOut |
| | | from stock_uninventory su |
| | | left join product_model pm on su.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | ) as combined |
| | | <where> |
| | | <if test="ew.productName != null and ew.productName !=''"> |
| | | and combined.product_name in ( |
| | | select distinct p.product_name |
| | | from product p |
| | | left join product_model pm on p.id = pm.product_id |
| | | where p.product_name like concat('%',#{ew.productName},'%') |
| | | or pm.model like concat('%',#{ew.productName},'%') |
| | | ) |
| | | </if> |
| | | <if test="ew.topParentProductId != null and ew.topParentProductId > 0"> |
| | | and combined.product_id in (select id from product_tree) |
| | | </if> |
| | | </where> |
| | | group by |
| | | product_model_id, |
| | | model, |
| | | unit, |
| | | product_name, |
| | | product_id |
| | | </select> |
| | | |
| | | <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData"> |
| | | WITH RECURSIVE product_tree AS ( |
| | | SELECT id |
| | | FROM product |
| | | WHERE id = #{ew.topParentProductId} |
| | | |
| | | UNION ALL |
| | | |
| | | SELECT p.id |
| | | FROM product p |
| | | INNER JOIN product_tree pt ON p.parent_id = pt.id |
| | | ) |
| | | select |
| | | batch_no, |
| | | MAX(qualifiedId) as qualifiedId, |
| | | MAX(unQualifiedId) as unQualifiedId, |
| | |
| | | </if> |
| | | </where> |
| | | group by batch_no, product_model_id, model, unit, product_name, product_id |
| | | </select> |
| | | |
| | | <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData"> |
| | | WITH RECURSIVE product_tree AS ( |
| | | SELECT id |
| | | FROM product |
| | | WHERE id = #{ew.topParentProductId} |
| | | |
| | | UNION ALL |
| | | |
| | | SELECT p.id |
| | | FROM product p |
| | | INNER JOIN product_tree pt ON p.parent_id = pt.id |
| | | ) |
| | | select |
| | | SUM(qualifiedQuantity) as qualifiedQuantity, |
| | | SUM(unQualifiedQuantity) as unQualifiedQuantity, |
| | | SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity, |
| | | SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity, |
| | | model, |
| | | unit, |
| | | product_name, |
| | | MAX(warn_num) as warn_num, |
| | | MAX(remark) as remark, |
| | | MAX(update_time) as update_time |
| | | from ( |
| | | select |
| | | si.qualitity as qualifiedQuantity, |
| | | 0 as unQualifiedQuantity, |
| | | COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity, |
| | | 0 as unQualifiedLockedQuantity, |
| | | si.product_model_id, |
| | | si.create_time, |
| | | si.update_time, |
| | | COALESCE(si.warn_num, 0) as warn_num, |
| | | si.remark, |
| | | pm.model, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id |
| | | from stock_inventory si |
| | | left join product_model pm on si.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | |
| | | union all |
| | | |
| | | select |
| | | 0 as qualifiedQuantity, |
| | | su.qualitity as unQualifiedQuantity, |
| | | 0 as qualifiedLockedQuantity, |
| | | COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity, |
| | | su.product_model_id, |
| | | su.create_time, |
| | | su.update_time, |
| | | 0 as warn_num, |
| | | su.remark, |
| | | pm.model, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id |
| | | from stock_uninventory su |
| | | left join product_model pm on su.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | ) as combined |
| | | <where> |
| | | <if test="ew.productName != null and ew.productName !=''"> |
| | | and combined.product_name in ( |
| | | select distinct p.product_name |
| | | from product p |
| | | left join product_model pm on p.id = pm.product_id |
| | | where p.product_name like concat('%',#{ew.productName},'%') or pm.model like concat('%',#{ew.productName},'%') |
| | | ) |
| | | </if> |
| | | <if test="ew.topParentProductId != null and ew.topParentProductId > 0"> |
| | | and combined.product_id in (select id from product_tree) |
| | | </if> |
| | | </where> |
| | | group by product_model_id, model, unit, product_name |
| | | </select> |
| | | <select id="stockInventoryPage" resultType="com.ruoyi.stock.dto.StockInRecordDto"> |
| | | select sir.*,si.qualitity as current_stock, |
| | |
| | | group by spd.stock_inventory_id |
| | | ) as sd on sd.stock_inventory_id = si.id |
| | | where si.product_model_id = #{productModelId} |
| | | and si.qualitity > IFNULL(sd.qualitity, 0) |
| | | </select> |
| | | |
| | | <select id="getBatchNoQty" resultType="com.ruoyi.stock.dto.StockInventoryDto"> |
| | | select |
| | | batch_no, |
| | | MAX(qualifiedId) as qualifiedId, |
| | | MAX(unQualifiedId) as unQualifiedId, |
| | | |
| | | SUM(qualifiedQuantity) as qualifiedQuantity, |
| | | SUM(unQualifiedQuantity) as unQualifiedQuantity, |
| | | |
| | | SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity, |
| | | SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity, |
| | | |
| | | SUM(IFNULL(qualifiedPendingOut, 0)) as qualifiedPendingOutQuantity, |
| | | SUM(IFNULL(unQualifiedPendingOut, 0)) as unQualifiedPendingOutQuantity, |
| | | |
| | | SUM(qualifiedQuantity - qualifiedLockedQuantity - IFNULL(qualifiedPendingOut, 0)) as qualifiedUnLockedQuantity, |
| | | SUM(unQualifiedQuantity - unQualifiedLockedQuantity - IFNULL(unQualifiedPendingOut, 0)) as unQualifiedUnLockedQuantity, |
| | | |
| | | product_model_id, |
| | | model, |
| | | unit, |
| | | product_name, |
| | | product_id, |
| | | |
| | | MAX(create_time) as create_time, |
| | | MAX(update_time) as update_time, |
| | | MAX(warn_num) as warn_num, |
| | | MAX(version) as version, |
| | | MAX(remark) as remark, |
| | | |
| | | 'combined' as stockType |
| | | from ( |
| | | select |
| | | si.batch_no, |
| | | si.id as qualifiedId, |
| | | null as unQualifiedId, |
| | | |
| | | si.qualitity as qualifiedQuantity, |
| | | 0 as unQualifiedQuantity, |
| | | |
| | | COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity, |
| | | 0 as unQualifiedLockedQuantity, |
| | | |
| | | si.product_model_id, |
| | | pm.model, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id, |
| | | |
| | | si.create_time, |
| | | si.update_time, |
| | | COALESCE(si.warn_num, 0) as warn_num, |
| | | si.version, |
| | | si.remark, |
| | | |
| | | ( |
| | | select IFNULL(SUM(sor.stock_out_num), 0) |
| | | from stock_out_record sor |
| | | where sor.product_model_id = si.product_model_id |
| | | and ( |
| | | (si.batch_no is null and sor.batch_no is null) |
| | | or si.batch_no = sor.batch_no |
| | | ) |
| | | and sor.type = '0' |
| | | and sor.approval_status = 0 |
| | | ) as qualifiedPendingOut, |
| | | |
| | | 0 as unQualifiedPendingOut |
| | | from stock_inventory si |
| | | left join product_model pm on si.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | |
| | | union all |
| | | |
| | | select |
| | | su.batch_no, |
| | | null as qualifiedId, |
| | | su.id as unQualifiedId, |
| | | |
| | | 0 as qualifiedQuantity, |
| | | su.qualitity as unQualifiedQuantity, |
| | | |
| | | 0 as qualifiedLockedQuantity, |
| | | COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity, |
| | | |
| | | su.product_model_id, |
| | | pm.model, |
| | | pm.unit, |
| | | p.product_name, |
| | | p.id as product_id, |
| | | |
| | | su.create_time, |
| | | su.update_time, |
| | | 0 as warn_num, |
| | | su.version, |
| | | su.remark, |
| | | |
| | | 0 as qualifiedPendingOut, |
| | | |
| | | ( |
| | | select IFNULL(SUM(sor.stock_out_num), 0) |
| | | from stock_out_record sor |
| | | where sor.product_model_id = su.product_model_id |
| | | and ( |
| | | (su.batch_no is null and sor.batch_no is null) |
| | | or su.batch_no = sor.batch_no |
| | | ) |
| | | and sor.type = '1' |
| | | and sor.approval_status = 0 |
| | | ) as unQualifiedPendingOut |
| | | from stock_uninventory su |
| | | left join product_model pm on su.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | ) as combined |
| | | <where> |
| | | <if test="ew.productModelId != null and ew.productModelId > 0"> |
| | | and combined.product_model_id = #{ew.productModelId} |
| | | </if> |
| | | |
| | | <if test="ew.productId != null and ew.productId > 0"> |
| | | and combined.product_id = #{ew.productId} |
| | | </if> |
| | | </where> |
| | | group by |
| | | batch_no, |
| | | product_model_id, |
| | | model, |
| | | unit, |
| | | product_name, |
| | | product_id |
| | | order by |
| | | batch_no |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | sor.id, |
| | | sor.outbound_batches, |
| | | sl.customer_name, |
| | | s.shipping_date, |
| | | sor.create_time as shippingDate, |
| | | p.product_name, |
| | | pm.model as specification_model, |
| | | sor.stock_out_num * slp.tax_inclusive_unit_price as outboundAmount, |
| | |
| | | LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | left join product_model pm on slp.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | | WHERE s.status='å·²åè´§' and sor.record_type='13' |
| | | WHERE sor.record_type='13' and sor.approval_status=1 |
| | | <if test="req.outboundBatches != null and req.outboundBatches != ''"> |
| | | AND sor.outbound_batches LIKE CONCAT('%',#{req.outboundBatches},'%') |
| | | </if> |
| | |
| | | AND sl.customer_name LIKE CONCAT('%',#{req.customerName},'%') |
| | | </if> |
| | | <if test="req.startDate != null and req.endDate != null"> |
| | | AND s.shipping_date BETWEEN #{startDate} AND #{endDate} |
| | | AND s.shipping_date BETWEEN #{req.startDate} AND #{req.endDate} |
| | | </if> |
| | | order by sor.id DESC |
| | | </select> |
| | |
| | | p.product_name as productName, |
| | | pm.product_id as productId, |
| | | pm.model, |
| | | top1.name as operationName |
| | | top1.name as operationName, |
| | | pm.product_code as productCode |
| | | from technology_bom_structure tbs |
| | | left join product_model pm on tbs.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |