doc/20260522_StockInRecordÁбíÔ´µ¥ºÅǰ¶ËÁªµ÷Îĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,75 @@ # StockInRecord å表æºåå·å端èè°ææ¡£ æ´æ°æ¶é´ï¼2026-05-22 éç¨æ¥å£ï¼`GET /stockInRecord/listPage` ## 1. åæ´è¯´æ æ¬æ¬¡å¯¹å ¥åºç®¡çå表æ¥å£å¢å è¿ååæ®µ `sourceOrderNo`ï¼æºåå·ï¼ï¼ç¨äºåææåºæ¯å±ç¤ºéè´æ¥æºåå·ã çææ¡ä»¶ï¼ - å½è¯·æ±åæ° `topParentProductId = 278` æ¶ï¼å端è¿å `sourceOrderNo`ã - å ¶ä» `topParentProductId` åºæ¯ä¸ï¼è¯¥å段è¿å `null`ï¼æä¸å±ç¤ºï¼ã ## 2. åæ®µå®ä¹ æ°å¢åæ®µï¼ - `sourceOrderNo`ï¼`string`ï¼æºåå·ï¼éè´ååå·ï¼ã ## 3. åå¼è§å ä» å¨ `topParentProductId = 278` æ¶æâæ¥æºâ计ç®ï¼ 1. æ¥æº = `éè´-å ¥åº`ï¼`recordType = 7`ï¼ - å æ `recordId` æ¥éè´äº§å表 `sales_ledger_product`ï¼`type=2`ï¼ï¼ - åéè¿ `sales_ledger_product.sales_ledger_id` æ¥éè´å°è´¦è¡¨ `purchase_ledger`ï¼ - è¿å `purchase_ledger.purchase_contract_number` ä½ä¸º `sourceOrderNo`ã - å ¼å®¹å åºï¼è¥æªå½ä¸éè´äº§åé¾è·¯ï¼åæ `recordId` ç´æ¥æ¥ `purchase_ledger.id` ååå·ã 2. æ¥æº = `éè´-è´¨æ£-åæ ¼å ¥åº`ï¼`recordType = 10`ï¼ - å æ `recordId` æ¥è´¨æ£è¡¨ `quality_inspect`ï¼ - åéè¿ `quality_inspect.purchase_ledger_id` æ¥éè´å°è´¦è¡¨ `purchase_ledger`ï¼ - è¿å `purchase_ledger.purchase_contract_number` ä½ä¸º `sourceOrderNo`ã ## 4. è¿åç¤ºä¾ ```json { "code": 200, "msg": "æä½æå", "data": { "records": [ { "id": 1024, "recordType": "7", "productName": "éæ", "model": "T2-30x3", "sourceOrderNo": "CG-2026-00128" }, { "id": 1025, "recordType": "10", "productName": "éæ", "model": "T2-30x3", "sourceOrderNo": "CG-2026-00131" } ], "total": 2 } } ``` ## 5. å端èè°å»ºè®® 1. åè¡¨åæ°å¢âæºåå·âï¼è¯»ååæ®µ `sourceOrderNo`ã 2. å»ºè®®ä» å¨ `topParentProductId = 278` ç页é¢/ç鿡件ä¸å±ç¤ºè¯¥åã 3. å½ `sourceOrderNo` 为空æ¶å±ç¤º `--`ï¼é¿å 空ç½ã ## 6. å彿¸ å 1. `topParentProductId=278` + `recordType=7`ï¼åºè¿åéè´ååå·ã 2. `topParentProductId=278` + `recordType=10`ï¼åºè¿åéè´ååå·ï¼ç»è´¨æ£é¾è·¯ï¼ã 3. `topParentProductId!=278`ï¼`sourceOrderNo` åºä¸º `null` æå端ä¸å±ç¤ºã 4. åæå段ï¼`productName/model/unit/createBy` çï¼ä¸åå½±åã doc/20260522_StockInRecordÁбíÔ´µ¥ºÅǰ¶ËÁªµ÷Îĵµ_276²¹³ä.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,65 @@ # StockInRecord å表æºåå·å端èè°ææ¡£ï¼`topParentProductId=276`è¡¥å ï¼ æ´æ°æ¶é´ï¼2026-05-22 éç¨æ¥å£ï¼`GET /stockInRecord/listPage` ## 1. åæ´è¯´æ å¨å·²æ `sourceOrderNo` åºç¡ä¸ï¼æ°å¢ `topParentProductId = 276` çæºåå·æº¯æºé»è¾ï¼ - æ ¹æ®âæ¥æºï¼recordTypeï¼+ recordIdâæº¯æºï¼ - ä¼å è¿åéå®åå·ï¼éå®ååå·ï¼ï¼ - è¥éå®åå·ä¸ºç©ºï¼ååéè¿åç产订åå·ï¼ - ä¸èèèªå®ä¹å ¥åºï¼`recordType=0/9`ï¼ã ## 2. è¿ååæ®µ åæ®µæ æ°å¢ï¼ç»§ç»ä½¿ç¨ï¼ - `sourceOrderNo`ï¼`string`ï¼æºåå·ã ## 3. 276 åºæ¯åå¼è§å 请æ±åæ°æ»¡è¶³ `topParentProductId = 276` æ¶ï¼ 1. `recordType = 14/15`ï¼éå®éè´§-åæ ¼/ä¸åæ ¼å ¥åºï¼ - `stock_in_record.record_id -> return_sale_product.id -> return_management.shipping_id -> shipping_info.sales_ledger_id -> sales_ledger.sales_contract_no` - è¿åéå®ååå·ã 2. `recordType = 2/5`ï¼ç产æ¥å·¥-å ¥åº/æ¥åºï¼ - `stock_in_record.record_id -> production_product_main.id -> production_operation_task.production_order_id -> production_order` - å å该ç产订åå ³èéå®ååå·ï¼ç±ç产计åå ³èéå®å°è´¦èåï¼ï¼ - éå®ååå·ä¸ºç©ºæ¶ï¼è¿å `production_order.nps_no`ã 3. `recordType = 6`ï¼è´¨æ£-åæ ¼å ¥åºï¼ - `stock_in_record.record_id -> quality_inspect.id -> quality_inspect.product_main_id -> production_product_main -> production_operation_task -> production_order` - å åéå®ååå·ï¼ç©ºååé `production_order.nps_no`ã 4. `recordType = 4/11`ï¼ä¸åæ ¼å¤ç-æ¥åº/è®©æ¥æ¾è¡ï¼ - `stock_in_record.record_id -> quality_unqualified.id -> quality_unqualified.inspect_id -> quality_inspect -> production_product_main -> production_operation_task -> production_order` - å åéå®ååå·ï¼ç©ºååé `production_order.nps_no`ã 5. `recordType = 20/22`ï¼é¢æéæ/ç产éæ-åæ ¼å ¥åºï¼ - `stock_in_record.record_id -> production_order_pick.id -> production_order` - å åéå®ååå·ï¼ç©ºååé `production_order.nps_no`ã 6. `recordType = 0/9`ï¼èªå®ä¹å ¥åºï¼ - ä¸å䏿º¯æºï¼`sourceOrderNo = null`ã ## 4. å ¶ä»åºæ¯è¯´æ - `topParentProductId = 278` çéè´é¾è·¯æºåå·é»è¾ä¿æä¸åã - å ¶ä» `topParentProductId` ä¸è§¦åæ¬æ¬¡ 276 è§åï¼`sourceOrderNo` 为空ã ## 5. å端èè°å»ºè®® 1. å¨ `topParentProductId=276` çåè¡¨åºæ¯å±ç¤ºâæºåå·âåï¼è¯»å `sourceOrderNo`ã 2. 建议空å¼ç»ä¸å±ç¤º `--`ã 3. ä¸éè¦æ°å¢è¯·æ±åæ°ï¼æ²¿ç¨ç°æ `/stockInRecord/listPage`ã ## 6. å彿¸ å 1. `topParentProductId=276` + `recordType=14/15`ï¼åºè¿åéå®ååå·ã 2. `topParentProductId=276` + `recordType=2/5/6/4/11/20/22`ï¼ä¼å éå®ååå·ï¼ç¼ºå¤±æ¶è¿åç产订åå·ã 3. `topParentProductId=276` + `recordType=0/9`ï¼`sourceOrderNo` 为空ã 4. `topParentProductId=278`ï¼ä»æéè´é¾è·¯è¿åéè´ååå·ã doc/20260522_²ÆÎñÖúÊÖÌáÎÊÓÅ»¯Ç°¶Ë±ä¸üÎĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,59 @@ # è´¢å¡å©ææé®ä¼ååç«¯åæ´ææ¡£ æ´æ°æ¶é´ï¼2026-05-22 éç¨æ¨¡åï¼è´¢å¡æºè½å©æï¼`/financial-ai`ï¼ ## 1. èæ¯ å½åé¦é¡µè´¢å¡å©æå¿«æ·æé®ä¸ºï¼ 1. `çææ¬å¨ç»è¥å¨æ¥` 2. `为ä»ä¹å©æ¶¦ä¸é` 3. `åªä¸ªå®¢æ·æèµé±` é®é¢ç¹ï¼ - 第 3 æ¡é®æ³å¨é¨ååºæ¯ä¸æå¾å½ä¸ä¸ç¨³å®ï¼å®¹æèµ°æ®éææ¬åçï¼å¯¼è´å¾è¡¨é¾æ¥ä»¥åå§ Markdown ææ¬å±ç¤ºï¼å¦ ``ï¼ã - å¿«æ·æé®ç¼ºå°æ¶é´èå´ååæç®æ ï¼ç»æç¨³å®æ§ä¸å¯è§£éæ§è¾å¼±ã ## 2. åç«¯å¿«æ·æé®ææ¡ä¼åï¼å¿ æ¹ï¼ 建议å°é»è®¤ä¸æ¡å¿«æ·æé®è°æ´ä¸ºï¼ 1. `çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼` 2. `åææ¬æå©æ¶¦ä¸éåå ` 3. `è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«` 说æï¼ - 䏿¡é®æ³å带æ¶é´èå´æåæç®æ ï¼å端å½ä¸æ´ç¨³å®ã - 第 3 æ¡ä¸âæèµé±å®¢æ·âè¯ä¹ä¸è´ï¼ä½â婿¶¦è´¡ç®æé«âæ´æç¡®ï¼éåç´æ¥é©±å¨å©æ¶¦åæç»æé¡µã ## 3. ä¸å端è½åæ å° | å¿«æ·æé® | 颿å½ä¸è½å | 颿 `type` | | --- | --- | --- | | çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼ | ç»è¥æ¥åçæ | `financial_operation_report` | | åææ¬æå©æ¶¦ä¸éåå | 订å婿¶¦åæ | `financial_order_profit_analysis` | | è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé« | 订å婿¶¦åæ | `financial_order_profit_analysis` | åç«¯å·²åæ¥å¢å¼ºâæèµé±å®¢æ·/客æ·å©æ¶¦æé«/婿¶¦è´¡ç®æé«âçåä¹é®æ³è¯å«ï¼å端æä»¥ä¸ææ¡æ¹é åå¯ç´æ¥èè°ã ## 4. è天å 容渲æå åºï¼å»ºè®®æ¹ï¼ é对è天è¿åææ¬ä¸åºç°çå¾è¡¨ Markdown 龿¥ï¼`https://local/generate_chart?options=...`ï¼ï¼å»ºè®®å端å¢å å åºå¤çï¼ 1. è¯å« Markdown å¾çè¯æ³ä¸ç `local/generate_chart` 龿¥ã 2. è§£æ `options` åæ°å¹¶è½¬æ¢ä¸º ECharts `option` 忏²æå¾è¡¨ç»ä»¶ã 3. è§£æå¤±è´¥æ¶ä¸å±ç¤ºåå§é¿é¾æ¥ææ¬ï¼å±ç¤ºç»ä¸ç©ºææç¤ºã ## 5. èè°å彿¸ å 1. ç¹å»å¿«æ·æé® `çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼` - æ ¡éªè¿å `type=financial_operation_report`ï¼å¹¶æ£å¸¸æ¸²ææè¦/建议/å¾è¡¨ã 2. ç¹å»å¿«æ·æé® `åææ¬æå©æ¶¦ä¸éåå ` - æ ¡éªè¿å `type=financial_order_profit_analysis`ï¼å¹¶å±ç¤ºäºæè®¢åä¸å®¢æ·å©æ¶¦æè¡ã 3. ç¹å»å¿«æ·æé® `è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«` - æ ¡éªè¿å `type=financial_order_profit_analysis`ï¼`summary.topCustomerByProfit` æå¼ã 4. æå·¥è¾å ¥ `åªä¸ªå®¢æ·æèµé±`ã`åªä¸ªå®¢æ·å©æ¶¦æé«` - æ ¡éªä»å½ä¸ `financial_order_profit_analysis`ï¼ä¸ååºç°åå§å¾è¡¨ Markdown 龿¥ç´åºã doc/20260522_²É¹ºÌ¨ÕËÈë¿â״̬_ÏúÊÛ²úÆ·Èë¿âÉóºË״̬ǰ¶ËÁªµ÷Îĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,127 @@ # éè´å ¥åºç¶æå端èè°ææ¡£ æ´æ°æ¶é´ï¼2026-05-22 éç¨çæ¬ï¼æ¬æ¬¡åç«¯åæ´å ## 1. åæ´èå´ 1. `GET /purchaseLedger/listPage` - æ°å¢æ¥è¯¢æ¡ä»¶ï¼`stockInStatus`ï¼å ¥åºç¶æï¼ - æ°å¢è¿ååæ®µï¼`stockInStatus`ï¼å ¥åºç¶æï¼ 2. `GET /salesLedgerProduct/list` - æ°å¢è¿ååæ®µï¼`stockInApprovalStatus`ï¼æ¯ä¸ªäº§åçå ¥åºå®¡æ ¸ç¶æï¼ --- ## 2. å ¥åºç¶ææä¸¾ï¼ä¸¤æ¥å£ä¸è´ï¼ - `å¾ å ¥åº` - `å ¥åºä¸` - `å®å ¨å ¥åº` 说æï¼å端çéå¼è¯·ç´æ¥ä½¿ç¨ä»¥ä¸ä¸ææä¸¾å¼ã --- ## 3. æ¥å£ä¸ï¼`GET /purchaseLedger/listPage` ### 3.1 æ°å¢è¯·æ±åæ° - `stockInStatus`ï¼`string`ï¼å¯é å¯ä¼ å¼ï¼`å¾ å ¥åº` / `å ¥åºä¸` / `å®å ¨å ¥åº` ### 3.2 æ°å¢è¿ååæ®µ - `stockInStatus`ï¼`string`ï¼éè´å°è´¦ç»´åº¦å ¥åºç¶æ ### 3.3 ç¶æè®¡ç®è§åï¼éè´å°è´¦ç»´åº¦ï¼ 以该éè´å°è´¦ä¸ `sales_ledger_product.type = 2` çéè´äº§å为计ç®èå´ï¼ 1. å ¨é¨äº§åé½è¾¾å°âå®å ¨å ¥åºâ => å°è´¦ç¶æ `å®å ¨å ¥åº` 2. è³å°æä¸ä¸ªäº§ååå¨âå®¡æ ¸éè¿å ¥åºâï¼ä½æªå ¨é¨å®å ¨å ¥åº => å°è´¦ç¶æ `å ¥åºä¸` 3. 没æä»»ä½äº§ååå¨âå®¡æ ¸éè¿å ¥åºâ => å°è´¦ç¶æ `å¾ å ¥åº` âå®¡æ ¸éè¿å ¥åºâç»è®¡å£å¾ï¼`stock_in_record.approval_status = 1`ï¼å¹¶æä»¥ä¸æ¥æºæº¯æºï¼ - `record_type = 7`ï¼éè´-å ¥åºï¼ï¼æéè´å°è´¦+产åå ³èç»è®¡ - `record_type = 10`ï¼éè´-è´¨æ£-åæ ¼å ¥åºï¼ï¼éè¿ `quality_inspect` åæº¯å°éè´å°è´¦+产åç»è®¡ ### 3.4 è¿å示ä¾ï¼èéï¼ ```json { "code": 200, "msg": "æä½æå", "data": { "records": [ { "id": 1201, "purchaseContractNumber": "CG20260522001", "supplierName": "XXä¾åºå", "stockInStatus": "å ¥åºä¸" } ], "total": 1 } } ``` --- ## 4. æ¥å£äºï¼`GET /salesLedgerProduct/list` ### 4.1 æ°å¢è¿ååæ®µ - `stockInApprovalStatus`ï¼`string`ï¼å½å产åè¡çå ¥åºå®¡æ ¸ç¶æ ### 4.2 ç¶æè®¡ç®è§åï¼äº§åç»´åº¦ï¼ ä» å½äº§å `type = 2`ï¼éè´äº§åï¼æ¶è®¡ç®å¹¶è¿åï¼ 1. å®¡æ ¸éè¿å ¥åºæ°é `<= 0` => `å¾ å ¥åº` 2. å®¡æ ¸éè¿å ¥åºæ°é `>= 产åéè´æ°é` => `å®å ¨å ¥åº` 3. å ¶ä»æ åµ => `å ¥åºä¸` å ¶ä¸âå®¡æ ¸éè¿å ¥åºæ°éâç»è®¡åæ ·åºäºï¼ - `stock_in_record.approval_status = 1` - æ¥æº `record_type = 7 / 10` çæº¯æºå ³èé»è¾ `type != 2` ç产åï¼è¯¥å段è¿å `null`ã ### 4.3 è¿å示ä¾ï¼èéï¼ ```json { "code": 200, "msg": "æä½æå", "data": [ { "id": 5566, "type": 2, "productCategory": "éæ", "specificationModel": "T2-30x3", "quantity": 100, "stockInApprovalStatus": "å¾ å ¥åº" } ] } ``` --- ## 5. å端æ¹é 建议 1. éè´å°è´¦å表æ°å¢âå ¥åºç¶æâçé项ï¼å¼åºå®ï¼`å¾ å ¥åº/å ¥åºä¸/å®å ¨å ¥åº`ã 2. éè´å°è´¦å表æ°å¢âå ¥åºç¶æâåï¼å±ç¤º `stockInStatus`ã 3. éè´äº§åå表æ°å¢âå ¥åºå®¡æ ¸ç¶æâåï¼å±ç¤º `stockInApprovalStatus`ã 4. 空å¼ï¼å¦ `type != 2`ï¼å»ºè®®å±ç¤ºä¸º `--`ã --- ## 6. èè°æ£æ¥æ¸ å 1. `/purchaseLedger/listPage` ä¸ä¼ `stockInStatus`ï¼åºæ£å¸¸è¿åå ¨é¨æ°æ®ï¼å¹¶å¸¦ `stockInStatus`ã 2. `/purchaseLedger/listPage?stockInStatus=å¾ å ¥åº`ï¼ä» è¿åå¾ å ¥åºå°è´¦ã 3. `/purchaseLedger/listPage?stockInStatus=å ¥åºä¸`ï¼ä» è¿åå ¥åºä¸å°è´¦ã 4. `/purchaseLedger/listPage?stockInStatus=å®å ¨å ¥åº`ï¼ä» è¿åå®å ¨å ¥åºå°è´¦ã 5. `/salesLedgerProduct/list` å¨éè´äº§åï¼`type=2`ï¼ä¸è¿å `stockInApprovalStatus`ã 6. `/salesLedgerProduct/list` å¨ééè´äº§åï¼`type!=2`ï¼ä¸ `stockInApprovalStatus` 为 `null`ã src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
@@ -4,6 +4,7 @@ import lombok.Data; import java.math.BigDecimal; import java.util.List; @Data @@ -16,13 +17,50 @@ @Schema(description = "æ»æ¯åº") private BigDecimal totalExpense; @Schema(description = "æ»æ¶å ¥ç¬æ°") private Integer incomeNumber; @Schema(description = "åºæ¶è´¦æ¬¾") private BigDecimal accountsReceivable; @Schema(description = "æ»æ¯åºç¬æ°") private Integer expenseNumber; @Schema(description = "åºä»è´¦æ¬¾") private BigDecimal accountsPayable; @Schema(description = "åæ¶å ¥") private BigDecimal netRevenue; // --- æçº¿å¾ï¼æåº¦è¶å¿æ°æ® --- @Schema(description = "æåº¦è¶å¿æ°æ®å表") private List<MonthlyTrendVO> monthlyTrendList; // --- æ±ç¶å¾ï¼åºæ¶åºä»æåº¦æ°æ® --- @Schema(description = "åºæ¶åºä»æåº¦æ°æ®å表") private List<ReceivablePayableVO> receivablePayableList; @Data @Schema(description = "æåº¦è¶å¿VOï¼æçº¿å¾ç¨ï¼") public static class MonthlyTrendVO { @Schema(description = "æä»½ï¼æ ¼å¼ï¼yyyy-MM") private String month; @Schema(description = "å½æè¥æ¶") private BigDecimal income; @Schema(description = "彿æ¯åº") private BigDecimal expense; @Schema(description = "彿å婿¶¦") private BigDecimal profit; } @Data @Schema(description = "åºæ¶åºä»æåº¦VOï¼æ±ç¶å¾ç¨ï¼") public static class ReceivablePayableVO { @Schema(description = "æä»½ï¼æ ¼å¼ï¼yyyy-MM") private String month; @Schema(description = "åºæ¶è´¦æ¬¾éé¢") private BigDecimal receivable; @Schema(description = "åºä»è´¦æ¬¾éé¢") private BigDecimal payable; } } src/main/java/com/ruoyi/account/controller/AccountingController.java
@@ -50,8 +50,8 @@ /*****************************************è´¢å¡æ¥è¡¨******************************************************************************/ @GetMapping("/accountStatementDetailsByMonth") @Log(title = "ç»è®¡æ»åºæ¶+æ»æ¯åº+æ»æ¶å ¥ç¬æ°+æ»æ¯åºç¬æ°+åæ¶å ¥", businessType = BusinessType.OTHER) @Operation(summary = "è´¢å¡æ¥è¡¨--ç»è®¡æ»åºæ¶+æ»æ¯åº+æ»æ¶å ¥ç¬æ°+æ»æ¯åºç¬æ°+åæ¶å ¥") @Log(title = "è´¢å¡æ¥è¡¨", businessType = BusinessType.OTHER) @Operation(summary = "è´¢å¡æ¥è¡¨") public R getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) { return R.ok(accountingService.getAccountStatementDetailsByMonth(accountReportDto)); } src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
@@ -6,6 +6,7 @@ import com.ruoyi.account.bean.dto.StatementAccountDto; import com.ruoyi.account.bean.vo.StatementAccountVo; import com.ruoyi.account.pojo.AccountStatement; import com.ruoyi.purchase.dto.VatDto; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -22,4 +23,6 @@ IPage<StatementAccountVo> listPageAccountStatement(Page page, @Param("req") StatementAccountDto statementAccountDto); IPage<VatDto> selectVatDtoPage(Page page, @Param("month") String month); } src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -8,7 +8,15 @@ import com.ruoyi.account.bean.dto.AccountReportDto; import com.ruoyi.account.bean.dto.DeviceTypeDetail; import com.ruoyi.account.bean.dto.DeviceTypeDistributionVO; import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto; import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto; import com.ruoyi.account.bean.dto.sales.SalesOutboundDto; import com.ruoyi.account.bean.dto.sales.SalesReturnDto; import com.ruoyi.account.bean.vo.AccountReportVo; import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo; import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo; import com.ruoyi.account.bean.vo.sales.SalesOutboundVo; import com.ruoyi.account.bean.vo.sales.SalesReturnVo; import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper; import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper; import com.ruoyi.account.pojo.purchase.AccountPurchasePayment; @@ -20,16 +28,22 @@ import com.ruoyi.procurementrecord.mapper.CustomStorageMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper; import com.ruoyi.procurementrecord.pojo.CustomStorage; import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; import com.ruoyi.stock.mapper.StockInRecordMapper; import com.ruoyi.stock.mapper.StockOutRecordMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Year; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -49,6 +63,10 @@ private final ProcurementRecordOutMapper procurementRecordOutMapper; private final AccountSalesCollectionMapper accountSalesCollectionMapper; private final AccountPurchasePaymentMapper accountPurchasePaymentMapper; private final StockOutRecordMapper stockOutRecordMapper; private final ReturnManagementMapper returnManagementMapper; private final StockInRecordMapper stockInRecordMapper; private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper; @Override @@ -285,20 +303,155 @@ @Override public AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) { AccountReportVo accountReportVo = new AccountReportVo(); //æ»è¥æ¶=æ¶æ¬¾åæ»éé¢ //æ»æ¶å ¥ç¬æ°=æ¶æ¬¾åæ»ç¬æ° List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(Wrappers.<AccountSalesCollection>lambdaQuery() .between(AccountSalesCollection::getCollectionDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd())); accountReportVo.setTotalIncome(accountSalesCollections.stream().map(AccountSalesCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); accountReportVo.setIncomeNumber(accountSalesCollections.size()); //æ»æ¯åº=仿¬¾åæ»éé¢ //æ»æ¯åºç¬æ°=仿¬¾åæ»ç¬æ° List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery() .between(AccountPurchasePayment::getPaymentDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd())); accountReportVo.setTotalExpense(accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); accountReportVo.setExpenseNumber(accountPurchasePayments.size()); //å婿¶¦=æ»è¥æ¶-æ»æ¯åº accountReportVo.setNetRevenue(accountReportVo.getTotalIncome().subtract(accountReportVo.getTotalExpense())); LocalDate start = accountReportDto.getEntryDateStart(); LocalDate end = accountReportDto.getEntryDateEnd(); DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // ========== 1. é¡¶é¨å¡çæ°æ® ========== // 1.1 æ»è¥æ¶ = æ¶æ¬¾åæ»éé¢ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList( Wrappers.<AccountSalesCollection>lambdaQuery() .between(AccountSalesCollection::getCollectionDate, start, end) ); BigDecimal totalIncome = Optional.of( accountSalesCollections.stream() .map(AccountSalesCollection::getCollectionAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setTotalIncome(totalIncome); // 1.2 æ»æ¯åº = 仿¬¾åæ»éé¢ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList( Wrappers.<AccountPurchasePayment>lambdaQuery() .between(AccountPurchasePayment::getPaymentDate, start, end) ); BigDecimal totalExpense = Optional.of( accountPurchasePayments.stream() .map(AccountPurchasePayment::getPaymentAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setTotalExpense(totalExpense); // 1.3 åºæ¶è´¦æ¬¾ = éå®åºåºéé¢å计 - éå®éè´§éé¢å计 SalesOutboundDto salesOutboundDto = new SalesOutboundDto(); salesOutboundDto.setStartDate(accountReportDto.getEntryDateStart()); salesOutboundDto.setEndDate(accountReportDto.getEntryDateEnd()); List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords(); BigDecimal salesOutAmount = Optional.of( salesOutboundVos.stream() .map(SalesOutboundVo::getOutboundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); SalesReturnDto salesReturnDto = new SalesReturnDto(); salesReturnDto.setStartDate(accountReportDto.getEntryDateStart()); salesReturnDto.setEndDate(accountReportDto.getEntryDateEnd()); List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords(); BigDecimal salesReturnAmount = Optional.of( salesReturnVos.stream() .map(SalesReturnVo::getRefundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setAccountsReceivable(salesOutAmount.subtract(salesReturnAmount)); // 1.4 åºä»è´¦æ¬¾ = éè´å ¥åºéé¢å计 - éè´éè´§éé¢å计 PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto(); purchaseInboundDto.setStartDate(accountReportDto.getEntryDateStart()); purchaseInboundDto.setEndDate(accountReportDto.getEntryDateEnd()); List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords(); BigDecimal purchaseInAmount = Optional.of( purchaseInboundVos.stream() .map(PurchaseInboundVo::getInboundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto(); purchaseReturnDto.setStartDate(accountReportDto.getEntryDateStart()); purchaseReturnDto.setEndDate(accountReportDto.getEntryDateEnd()); List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords(); BigDecimal purchaseReturnAmount = Optional.of( purchaseReturnVos.stream() .map(PurchaseReturnVo::getTotalAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setAccountsPayable(purchaseInAmount.subtract(purchaseReturnAmount)); // 1.5 å婿¶¦ = æ»è¥æ¶ - æ»æ¯åº BigDecimal netProfit = totalIncome.subtract(totalExpense); accountReportVo.setNetRevenue(netProfit); // ========== 2. æçº¿å¾ï¼æåº¦è¥æ¶/æ¯åº/å婿¶¦è¶å¿ ========== Map<String, BigDecimal> monthIncomeMap = new HashMap<>(); Map<String, BigDecimal> monthExpenseMap = new HashMap<>(); // æåº¦è¥æ¶ accountSalesCollections.forEach(item -> { String month = item.getCollectionDate().format(monthFormatter); monthIncomeMap.put(month, monthIncomeMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getCollectionAmount()).orElse(BigDecimal.ZERO))); }); // æåº¦æ¯åº accountPurchasePayments.forEach(item -> { String month = item.getPaymentDate().format(monthFormatter); monthExpenseMap.put(month, monthExpenseMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getPaymentAmount()).orElse(BigDecimal.ZERO))); }); // çæè¿ç»æä»½å表 List<String> monthList = new ArrayList<>(); LocalDate current = start.withDayOfMonth(1); while (!current.isAfter(end.withDayOfMonth(1))) { monthList.add(current.format(monthFormatter)); current = current.plusMonths(1); } // ç»è£ è¶å¿æ°æ® List<AccountReportVo.MonthlyTrendVO> trendList = new ArrayList<>(); for (String month : monthList) { BigDecimal income = monthIncomeMap.getOrDefault(month, BigDecimal.ZERO); BigDecimal expense = monthExpenseMap.getOrDefault(month, BigDecimal.ZERO); AccountReportVo.MonthlyTrendVO trend = new AccountReportVo.MonthlyTrendVO(); trend.setMonth(month); trend.setIncome(income); trend.setExpense(expense); trend.setProfit(income.subtract(expense)); trendList.add(trend); } accountReportVo.setMonthlyTrendList(trendList); // ========== 3. æ±ç¶å¾ï¼æåº¦åºæ¶/åºä»æ°æ® ========== Map<String, BigDecimal> monthReceivableMap = new HashMap<>(); Map<String, BigDecimal> monthPayableMap = new HashMap<>(); // æåº¦åºæ¶ï¼éå®åºåº-éè´§ï¼ salesOutboundVos.forEach(item -> { String month = item.getShippingDate().format(monthFormatter); monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getOutboundAmount()).orElse(BigDecimal.ZERO))); }); salesReturnVos.forEach(item -> { String month = item.getMakeTime().format(monthFormatter); monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO) .subtract(Optional.ofNullable(item.getRefundAmount()).orElse(BigDecimal.ZERO))); }); // æåº¦åºä»ï¼éè´å ¥åº-éè´§ï¼ purchaseInboundVos.forEach(item -> { String month = item.getInboundDate().format(monthFormatter); monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getInboundAmount()).orElse(BigDecimal.ZERO))); }); purchaseReturnVos.forEach(item -> { String month = item.getPreparedAt().format(monthFormatter); monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO) .subtract(Optional.ofNullable(item.getTotalAmount()).orElse(BigDecimal.ZERO))); }); // ç»è£ åºæ¶åºä»æ°æ® List<AccountReportVo.ReceivablePayableVO> rpList = new ArrayList<>(); for (String month : monthList) { AccountReportVo.ReceivablePayableVO rp = new AccountReportVo.ReceivablePayableVO(); rp.setMonth(month); rp.setReceivable(monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)); rp.setPayable(monthPayableMap.getOrDefault(month, BigDecimal.ZERO)); rpList.add(rp); } accountReportVo.setReceivablePayableList(rpList); return accountReportVo; } } src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
@@ -45,7 +45,8 @@ if (containsAny(text, "ææ¬æ ¸ç®", "äº§åææ¬", "å·¥åºææ¬", "äººå·¥ææ¬", "ææ§", "æææè")) { return financialAgentTools.calculateIntelligentCost(memoryId, startDate, endDate, timeRange, keyword, limit); } if (containsAny(text, "婿¶¦åæ", "订å婿¶¦", "äºæè®¢å", "ä½å©æ¶¦", "æèµé±å®¢æ·", "婿¶¦ä¸é")) { if (containsAny(text, "婿¶¦åæ", "订å婿¶¦", "äºæè®¢å", "ä½å©æ¶¦", "æèµé±å®¢æ·", "åªä¸ªå®¢æ·æèµé±", "å®¢æ·æèµé±", "婿¶¦æé«å®¢æ·", "婿¶¦è´¡ç®æé«å®¢æ·", "婿¶¦ä¸é")) { return financialAgentTools.analyzeOrderProfit(memoryId, startDate, endDate, timeRange, keyword, limit); } if (containsAny(text, "åºåèµé", "åºå积å", "åæ»åºå", "èµéå ç¨", "å¨è½¬ç", "åºåå¨è½¬")) { @@ -86,6 +87,15 @@ } if ("为ä»ä¹å©æ¶¦ä¸é".equals(normalized)) { DateRange range = monthRange(); return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20); } if ("åªä¸ªå®¢æ·æèµé±".equals(normalized) || "æè¿åªä¸ªå®¢æ·æèµé±".equals(normalized) || "æ¬æåªä¸ªå®¢æ·æèµé±".equals(normalized) || "è¿30天åªä¸ªå®¢æ·æèµé±".equals(normalized) || "åªä¸ªå®¢æ·å©æ¶¦æé«".equals(normalized) || "åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«".equals(normalized)) { DateRange range = extractDateRange(text); return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20); } return null; @@ -216,6 +226,16 @@ .replace("请", "") .replace("ä¸ä¸", "") .replace("为ä»ä¹", "") .replace("åªä¸ªå®¢æ·æèµé±", "") .replace("æè¿åªä¸ªå®¢æ·æèµé±", "") .replace("æ¬æåªä¸ªå®¢æ·æèµé±", "") .replace("è¿30天åªä¸ªå®¢æ·æèµé±", "") .replace("æèµé±å®¢æ·", "") .replace("å®¢æ·æèµé±", "") .replace("åªä¸ªå®¢æ·å©æ¶¦æé«", "") .replace("婿¶¦æé«å®¢æ·", "") .replace("åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«", "") .replace("婿¶¦è´¡ç®æé«å®¢æ·", "") .replace("æ¬æ", "") .replace("æ¬å¨", "") .replace("æ¬å¹´", "") src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
@@ -19,10 +19,10 @@ @Schema(description = "åºä»éé¢") private BigDecimal payableMoney; @Schema(description = "颿¶éé¢") @Schema(description = "æ¶æ¬¾éé¢") private BigDecimal advanceMoney; @Schema(description = "é¢ä»éé¢") @Schema(description = "仿¬¾éé¢") private BigDecimal prepayMoney; } src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,10 +3,18 @@ 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.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto; import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto; import com.ruoyi.account.bean.dto.sales.SalesOutboundDto; import com.ruoyi.account.bean.dto.sales.SalesReturnDto; import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo; import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo; import com.ruoyi.account.bean.vo.sales.SalesOutboundVo; import com.ruoyi.account.bean.vo.sales.SalesReturnVo; import com.ruoyi.account.mapper.AccountStatementMapper; import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper; import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper; import com.ruoyi.account.pojo.AccountStatement; import com.ruoyi.account.pojo.purchase.AccountPurchasePayment; import com.ruoyi.account.pojo.sales.AccountSalesCollection; import com.ruoyi.approve.mapper.ApproveProcessMapper; @@ -29,11 +37,13 @@ import com.ruoyi.home.dto.*; import com.ruoyi.home.mapper.HomeMapper; import com.ruoyi.home.service.HomeService; import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper; import com.ruoyi.production.bean.dto.ProductionProductOutputDto; import com.ruoyi.production.mapper.*; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; @@ -45,7 +55,9 @@ import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.staff.mapper.StaffOnJobMapper; import com.ruoyi.staff.pojo.StaffOnJob; import com.ruoyi.stock.mapper.StockInRecordMapper; import com.ruoyi.stock.mapper.StockInventoryMapper; import com.ruoyi.stock.mapper.StockOutRecordMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -71,6 +83,10 @@ public class HomeServiceImpl implements HomeService { private final SalesLedgerMapper salesLedgerMapper; private final StockOutRecordMapper stockOutRecordMapper; private final ReturnManagementMapper returnManagementMapper; private final StockInRecordMapper stockInRecordMapper; private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper; private final PurchaseLedgerMapper purchaseLedgerMapper; @@ -297,19 +313,35 @@ queryWrapper.ge(QualityInspect::getCheckTime, monthStart.toString()) .le(QualityInspect::getCheckTime, monthEnd.toString()); List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper); // ç»è®¡æ»æ°éï¼åæ ¼æ°é + ä¸åæ ¼æ°éï¼ BigDecimal reduce = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); supplierNum = supplierNum.add(reduce); BigDecimal reduce1 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); processNum = processNum.add(reduce1); BigDecimal reduce2 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); factoryNum = factoryNum.add(reduce2); @@ -319,25 +351,22 @@ // 1. ä¾åºåæ£éªï¼ç±»å0ï¼- åæ ¼æ°é BigDecimal supplierQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(0)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSupplierNum(supplierQualified); // 2. å·¥åºæ£éªï¼ç±»å1ï¼- åæ ¼æ°é BigDecimal processQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(1)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setProcessNum(processQualified); // 3. 工忣éªï¼ç±»å2ï¼- åæ ¼æ°é BigDecimal factoryQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(2)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setFactoryNum(factoryQualified); @@ -404,14 +433,26 @@ LocalDate startDate = range[0]; LocalDate endDate = range[1]; //éå®åºåº BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate); //éå®éè´§ BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate); //éè´å ¥åº BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate); //éè´éè´§ BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate); //æ¶æ¬¾ BigDecimal advanceMoney = sumCollectionAmount(startDate, endDate); //仿¬¾ BigDecimal prepayMoney = sumPaymentAmount(startDate, endDate); dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(advanceMoney)))); dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(prepayMoney)))); //åºæ¶éé¢=éå®åºåº-éå®éè´§ dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(salesReturnAmount)))); //åºä»éé¢=éè´å ¥åº-éè´éè´§ dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(purchaseReturnAmount)))); //æ¶æ¬¾éé¢=æ¶æ¬¾å dto.setAdvanceMoney(scaleMoney(advanceMoney)); //仿¬¾éé¢=仿¬¾å dto.setPrepayMoney(scaleMoney(prepayMoney)); return dto; } @@ -1226,33 +1267,21 @@ YearMonth currentMonth = YearMonth.from(today); LocalDate startDate = currentMonth.atDay(1); LocalDate endDate = currentMonth.atEndOfMonth(); //æ¶æ¬¾ BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate); //éå®åºåº BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate); String collectionRate = toRateString(monthlyIncome, receivableBase); String currentMonthText = currentMonth.toString(); List<AccountStatement> receivableStatements = defaultList(accountStatementMapper.selectList( new LambdaQueryWrapper<AccountStatement>() .eq(AccountStatement::getAccountType, 1) .le(AccountStatement::getStatementMonth, currentMonthText))); long overdueNum = receivableStatements.stream() .filter(item -> item.getStatementMonth() != null && item.getStatementMonth().compareTo(currentMonthText) < 0) .filter(item -> defaultDecimal(item.getClosingBalance()).compareTo(BigDecimal.ZERO) > 0) .count(); long totalReceivableCount = receivableStatements.size(); String overdueRate = totalReceivableCount == 0 ? "0.00" : BigDecimal.valueOf(overdueNum) .multiply(BigDecimal.valueOf(100)) .divide(BigDecimal.valueOf(totalReceivableCount), 2, RoundingMode.HALF_UP) .toString(); //éå®éè´§ BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate); //忬¾ç=æ¶æ¬¾/(éå®åºåº-éå®éè´§)åºæ¶ String collectionRate = toRateString(monthlyIncome, receivableBase.subtract(salesReturnAmount)); //龿æ°=(éå®åºåºéé¢-éå®éè´§éé¢)åºæ¶éé¢-æ¶æ¬¾éé¢ BigDecimal overdueAmount = receivableBase.subtract(salesReturnAmount).subtract(monthlyIncome); //龿ç=龿æ°/åºæ¶éé¢ String overdueRate = toRateString(overdueAmount, receivableBase); dto.setMonthlyIncome(scaleMoney(monthlyIncome)); dto.setCollectionRate(collectionRate); dto.setOverdueNum(BigDecimal.valueOf(overdueNum)); dto.setOverdueNum(overdueAmount); dto.setOverdueRate(overdueRate); return dto; } @@ -1264,16 +1293,25 @@ YearMonth currentMonth = YearMonth.from(today); LocalDate startDate = currentMonth.atDay(1); LocalDate endDate = currentMonth.atEndOfMonth(); //æ¯åº BigDecimal monthlyExpenditure = sumPaymentAmount(startDate, endDate); //éè´å ¥åº BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate); //éè´éè´§ BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate); //仿¬¾ç=仿¬¾/(éè´å ¥åº-éè´éè´§)åºä» String paymentRate = toRateString(monthlyExpenditure, payableBase.subtract(purchaseReturnAmount)); //æ¶æ¬¾ BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate); //æ¯å©æ¶¦= æ¶æ¬¾-æ¯åº BigDecimal grossProfit = monthlyIncome.subtract(monthlyExpenditure); //婿¶¦ç=æ¯å©æ¶¦/æ¶æ¬¾ String profitMarginRate = toRateString(grossProfit, monthlyIncome); dto.setMonthlyExpenditure(scaleMoney(monthlyExpenditure)); dto.setPaymentRate(toRateString(monthlyExpenditure, payableBase)); dto.setPaymentRate(paymentRate); dto.setGrossProfit(scaleMoney(grossProfit)); dto.setProfitMarginRate(toRateString(grossProfit, monthlyIncome)); dto.setProfitMarginRate(profitMarginRate); return dto; } @@ -1712,11 +1750,8 @@ BigDecimal unqualifiedCount = BigDecimal.ZERO; for (QualityInspect item : list) { if ("åæ ¼".equals(item.getCheckResult())) { qualifiedCount = qualifiedCount.add(item.getQuantity()); } else { unqualifiedCount = unqualifiedCount.add(item.getQuantity()); } qualifiedCount = qualifiedCount.add(item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO); unqualifiedCount = unqualifiedCount.add(item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO); } BigDecimal totalCount = qualifiedCount.add(unqualifiedCount); @@ -1985,13 +2020,11 @@ continue; } BigDecimal quantity = item.getQuantity(); BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; if ("åæ ¼".equals(item.getCheckResult())) { dto.setQualifiedCount(dto.getQualifiedCount().add(quantity)); } else { dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity)); } dto.setQualifiedCount(dto.getQualifiedCount().add(qualifiedQty)); dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(unqualifiedQty)); } // 计ç®åæ ¼ç @@ -2032,14 +2065,12 @@ BigDecimal unqualifiedCount = BigDecimal.ZERO; for (QualityInspect item : items) { BigDecimal qty = item.getQuantity(); totalCount = totalCount.add(qty); BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; if ("åæ ¼".equals(item.getCheckResult())) { qualifiedCount = qualifiedCount.add(qty); } else { unqualifiedCount = unqualifiedCount.add(qty); } totalCount = totalCount.add(qualifiedQty.add(unqualifiedQty)); qualifiedCount = qualifiedCount.add(qualifiedQty); unqualifiedCount = unqualifiedCount.add(unqualifiedQty); } if (totalCount.compareTo(BigDecimal.ZERO) == 0) { @@ -2168,13 +2199,17 @@ dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // è¿ç¨ dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // åºå // å设 qualityInspectList æ¯ä¸ä¸ª List<QualityInspect> ç±»åçéå Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream() .collect(Collectors.groupingBy(QualityInspect::getCheckResult)); List<QualityInspect> qualityInspects = groupedByCheckResult.get("ä¸åæ ¼"); if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) { return null; // æ ¹æ® unqualifiedQuantity > 0 çéä¸åæ ¼è®°å½ List<QualityInspect> qualityInspects = qualityInspectList.stream() .filter(i -> i.getUnqualifiedQuantity() != null && i.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) .collect(Collectors.toList()); if (ObjectUtils.isEmpty(qualityInspects)) { // å³ä½¿æ²¡æä¸åæ ¼è®°å½ï¼ä¹åºè¯¥è¿åç»è®¡æ°æ®ï¼åªæ¯å¾è¡¨é¡¹ä¸ºç©º dto.setItem(new ArrayList<>()); return dto; } // 4. å¤çå¾è¡¨é¡¹ (Item) List<QualityStatisticsItem> itemList = new ArrayList<>(); @@ -2217,8 +2252,11 @@ private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) { return list.stream() .filter(i -> i.getInspectType().equals(type)) .map(QualityInspect::getQuantity) .filter(Objects::nonNull) .map(i -> { BigDecimal qualified = i.getQualifiedQuantity() != null ? i.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); } @@ -2226,11 +2264,18 @@ QualityStatisticsItem item = new QualityStatisticsItem(); item.setDate(dateLabel); item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity) // ç»è®¡æ¯ç§æ£éªç±»åçä¸åæ ¼æ°é item.setSupplierNum(list.stream() .filter(i -> i.getInspectType() == 0) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity) item.setProcessNum(list.stream() .filter(i -> i.getInspectType() == 1) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity) item.setFactoryNum(list.stream() .filter(i -> i.getInspectType() == 2) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); return item; @@ -2297,20 +2342,43 @@ return new LocalDate[]{startDate, endDate}; } //è®¡ç®æ¥æå çéå®åºåºéé¢ private BigDecimal sumSalesContractAmount(LocalDate startDate, LocalDate endDate) { List<SalesLedger> salesLedgers = defaultList(salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>() .ge(SalesLedger::getEntryDate, toDate(startDate)) .lt(SalesLedger::getEntryDate, toExclusiveEndDate(endDate)))); return sumAmount(salesLedgers, SalesLedger::getContractAmount); SalesOutboundDto salesOutboundDto = new SalesOutboundDto(); salesOutboundDto.setStartDate(startDate); salesOutboundDto.setEndDate(endDate); List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords(); return sumAmount(salesOutboundVos, SalesOutboundVo::getOutboundAmount); } //è®¡ç®æ¥æå çéå®éè´§éé¢ private BigDecimal sumSalesReturnAmount(LocalDate startDate, LocalDate endDate) { SalesReturnDto salesReturnDto = new SalesReturnDto(); salesReturnDto.setStartDate(startDate); salesReturnDto.setEndDate(endDate); List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords(); return sumAmount(salesReturnVos, SalesReturnVo::getRefundAmount); } //è®¡ç®æ¥æå çéè´å ¥åºéé¢ private BigDecimal sumPurchaseContractAmount(LocalDate startDate, LocalDate endDate) { List<PurchaseLedger> purchaseLedgers = defaultList(purchaseLedgerMapper.selectList(new LambdaQueryWrapper<PurchaseLedger>() .ge(PurchaseLedger::getEntryDate, toDate(startDate)) .lt(PurchaseLedger::getEntryDate, toExclusiveEndDate(endDate)))); return sumAmount(purchaseLedgers, PurchaseLedger::getContractAmount); PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto(); purchaseInboundDto.setStartDate(startDate); purchaseInboundDto.setEndDate(endDate); List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords(); return sumAmount(purchaseInboundVos, PurchaseInboundVo::getInboundAmount); } //è®¡ç®æ¥æå çéè´éè´§éé¢ private BigDecimal sumPurchaseReturnAmount(LocalDate startDate, LocalDate endDate) { PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto(); purchaseReturnDto.setStartDate(startDate); purchaseReturnDto.setEndDate(endDate); List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords(); return sumAmount(purchaseReturnVos, PurchaseReturnVo::getTotalAmount); } //è®¡ç®æ¥æå çæ»æ¶æ¬¾éé¢ private BigDecimal sumCollectionAmount(LocalDate startDate, LocalDate endDate) { List<AccountSalesCollection> collections = defaultList(accountSalesCollectionMapper.selectList( new LambdaQueryWrapper<AccountSalesCollection>() @@ -2319,6 +2387,7 @@ return sumAmount(collections, AccountSalesCollection::getCollectionAmount); } //è®¡ç®æ¥æå çæ»ä»æ¬¾éé¢ private BigDecimal sumPaymentAmount(LocalDate startDate, LocalDate endDate) { List<AccountPurchasePayment> payments = defaultList(accountPurchasePaymentMapper.selectList( new LambdaQueryWrapper<AccountPurchasePayment>() src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -120,10 +120,7 @@ List<SysRole> roles = roleService.selectRoleAll(); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll()); SysUserDeptVo sysUserDeptVo = new SysUserDeptVo(); sysUserDeptVo.setUserId(userId); List<SysUserDeptVo> sysUserDeptVos = userDeptService.userLoginFacotryList(sysUserDeptVo); ajax.put("deptIds",sysUserDeptVos.stream().map(SysUserDeptVo::getDeptId).collect(Collectors.toList())); ajax.put("deptIds", userService.selectDeptIdsByUserId(userId)); return ajax; } src/main/java/com/ruoyi/project/system/service/ISysUserService.java
@@ -217,4 +217,11 @@ * @return */ int bindUserDept(SysUser user); /** * æ ¹æ®ç¨æ·IDæ¥è¯¢ææå ³èçé¨é¨ID * @param userId * @return */ List<Long> selectDeptIdsByUserId(Long userId); } src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
@@ -560,4 +560,11 @@ } return user.getDeptIds().length; } @Override public List<Long> selectDeptIdsByUserId(Long userId) { LambdaQueryWrapper<SysUserDept> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SysUserDept::getUserId, userId); return sysUserDeptMapper.selectList(queryWrapper).stream().map(SysUserDept::getDeptId).collect(Collectors.toList()); } } src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
@@ -2,10 +2,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.service.ISupplierService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.service.PurchaseReportService; import com.ruoyi.purchase.vo.PurchaseReportVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; @@ -15,6 +18,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @Tag(name = "éè´æ¥è¡¨") @RequestMapping("/purchase/report") @@ -22,31 +27,38 @@ public class AccountingReportController { private final ISupplierService supplierService; private final PurchaseReportService purchaseReportService; @GetMapping("/list") @Log(title = "éè´æ¥è¡¨-项ç®å©æ¶¦", businessType = BusinessType.OTHER) public AjaxResult list(Page page) { return AjaxResult.success(); public R list(Page page, String customerName) { return R.ok(purchaseReportService.list(page,customerName)); } @Log(title = "éè´æ¥è¡¨-项ç®å©æ¶¦å¯¼åº", businessType = BusinessType.EXPORT) @PostMapping("/export") @Operation(summary = "éè´æ¥è¡¨-项ç®å©æ¶¦å¯¼åº") public void export(HttpServletResponse response) { public void export(HttpServletResponse response, String customerName) { List<PurchaseReportVo> list = purchaseReportService.list(new Page(1,-1),customerName).getRecords(); ExcelUtil<PurchaseReportVo> util = new ExcelUtil<>(PurchaseReportVo.class); util.exportExcel(response, list , "项ç®å©æ¶¦"); } @Log(title = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹", businessType = BusinessType.OTHER) @GetMapping("/listVat") public AjaxResult listVat(Page page,String month) { return AjaxResult.success(); public R listVat(Page page,String month) { return R.ok(purchaseReportService.listVat(page,month)); } @Log(title = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹", businessType = BusinessType.EXPORT) @PostMapping("/exportTwo") @Operation(summary = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹") public void exportTwo(HttpServletResponse response) { public void exportTwo(HttpServletResponse response,String month) { List<VatDto> list = purchaseReportService.listVat(new Page(1,-1),month).getRecords(); ExcelUtil<VatDto> util = new ExcelUtil<>(VatDto.class); util.exportExcel(response, list , "å¢å¼ç¨æ¯å¯¹"); } @GetMapping("/supplierTransactions") src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -27,6 +27,8 @@ private String entryDateStart; private String entryDateEnd; @Schema(description = "å ¥åºç¶æ") private String stockInStatus; private Long id; src/main/java/com/ruoyi/purchase/dto/VatDto.java
@@ -1,27 +1,30 @@ package com.ruoyi.purchase.dto; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; @Data @Schema(name = "VatDto", description = "管ç驾驶è±--å¢å¼ç¨æ¯å¯¹åæ°") @ExcelIgnoreUnannotated public class VatDto { //æä»½ @Excel(name = "æä»½") @Schema(description = "æä»½") private String month ; //è¿é¡¹ç¨ @Excel(name = "è¿é¡¹ç¨é¢") @Excel(name = "é项ç¨é¢") @Schema(description = "é项ç¨é¢") private BigDecimal jTaxAmount; //éé¡¹ç¨ @Excel(name = "é项ç¨é¢") @Excel(name = "è¿é¡¹ç¨é¢") @Schema(description = "è¿é¡¹ç¨é¢") private BigDecimal xTaxAmount; @Excel(name = "é-è¿") @Schema(description = "é-è¿") private BigDecimal taxAmount; } src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,14 @@ package com.ruoyi.purchase.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.vo.PurchaseReportVo; public interface PurchaseReportService { IPage<PurchaseReportVo> list(Page page, String customerName); IPage<VatDto> listVat(Page page, String month); } src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -451,12 +451,7 @@ @Override public IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, PurchaseLedgerDto purchaseLedger) { IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger); purchaseLedgerDtoIPage.getRecords().forEach(purchaseLedgerDto -> { List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, purchaseLedgerDto.getId()).eq(CommonFile::getType, FileNameType.PURCHASE.getValue())); purchaseLedgerDto.setSalesLedgerFiles(commonFiles); }); return purchaseLedgerDtoIPage; return purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger); } @Override src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,32 @@ package com.ruoyi.purchase.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.account.mapper.AccountStatementMapper; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.service.PurchaseReportService; import com.ruoyi.purchase.vo.PurchaseReportVo; import com.ruoyi.sales.mapper.SalesLedgerMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor public class PurchaseReportServiceImpl implements PurchaseReportService { private final SalesLedgerMapper salesLedgerMapper; private final AccountStatementMapper accountStatementMapper; @Override public IPage<PurchaseReportVo> list(Page page, String customerName) { return salesLedgerMapper.selectPurchaseReportVoPage(page, customerName); } @Override public IPage<VatDto> listVat(Page page, String month) { return accountStatementMapper.selectVatDtoPage(page, month); } } src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,44 @@ package com.ruoyi.purchase.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; @Data @Schema(name = "PurchaseReportVo", description = "管ç驾驶è±--项ç®å©æ¶¦åæ°") @ExcelIgnoreUnannotated public class PurchaseReportVo { @Schema(description = "éå®ååå·") @Excel(name = "éå®ååå·") private String customerContractNo; @Schema(description = "客æ·åç§°") @Excel(name = "客æ·åç§°") private String customerName; @Schema(description = "项ç®åç§°") @Excel(name = "项ç®åç§°") private String projectName; @Excel(name = "ååéé¢") @Schema(description = "ååéé¢") private BigDecimal contractAmount; @Excel(name = "éè´éé¢") @Schema(description = "éè´éé¢") private BigDecimal purchaseAmount; @Schema(description = "婿¶¦") @Excel(name = "婿¶¦") private BigDecimal balance; @Schema(description = "婿¶¦ç") @Excel(name = "婿¶¦ç") private BigDecimal balanceRatio; } src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
@@ -14,7 +14,6 @@ import com.ruoyi.quality.service.IQualityInspectService; import io.swagger.v3.oas.annotations.Operation; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.AllArgsConstructor; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; @@ -139,7 +138,7 @@ @PostMapping("/submit") @Operation(summary = "æäº¤æ£éª") @Log(title = "æäº¤æ£éª", businessType = BusinessType.OTHER) public R<?> submit(@Valid @RequestBody QualityInspect qualityInspect) { public R<?> submit(@RequestBody QualityInspect qualityInspect) { return R.ok(qualityInspectService.submit(qualityInspect)); } src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -5,7 +5,6 @@ import com.ruoyi.dto.DateQueryDto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; import java.io.Serial; @@ -34,7 +33,6 @@ * ç±»å«(0:åæææ£éª;1:è¿ç¨æ£éª;2:åºåæ£éª) */ @Excel(name = "ç±»å«",readConverterExp = "0=åæææ£éª,1=è¿ç¨æ£éª,2=åºåæ£éª") @NotNull(message = "ç±»å«ä¸è½ä¸ºç©º") private Integer inspectType; /** @@ -74,7 +72,6 @@ /** * å ³è产åid */ @NotNull(message = "产åidä¸è½ä¸ºç©º") private Long productId; /** @@ -103,12 +100,10 @@ @Excel(name = "åæ ¼æ°é") @TableField("qualified_quantity") @NotNull(message = "åæ ¼æ°éä¸è½ä¸ºç©º") private BigDecimal qualifiedQuantity; @Excel(name = "ä¸åæ ¼æ°é") @TableField("unqualified_quantity") @NotNull(message = "ä¸åæ ¼æ°éä¸è½ä¸ºç©º") private BigDecimal unqualifiedQuantity; /** src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -10,6 +10,7 @@ import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.HackLoopTableRenderPolicy; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.procurementrecord.service.ProcurementRecordService; @@ -90,24 +91,32 @@ @Override public int submit(QualityInspect inspect) { QualityInspect qualityInspect = qualityInspectMapper.selectById(inspect.getId()); //æäº¤åå¿ é¡»å¤ææ¯å¦åæ ¼ if (ObjectUtils.isNull(qualityInspect.getCheckResult())) { throw new RuntimeException("请å 夿æ¯å¦åæ ¼"); throw new ServiceException("请å 夿æ¯å¦åæ ¼"); } if (ObjectUtils.isNull(qualityInspect.getQualifiedQuantity())) { throw new RuntimeException("åæ ¼æ°éä¸è½ä¸ºç©º"); throw new ServiceException("åæ ¼æ°éä¸è½ä¸ºç©º"); } if (ObjectUtils.isNull(qualityInspect.getUnqualifiedQuantity())) { throw new RuntimeException("ä¸åæ ¼æ°éä¸è½ä¸ºç©º"); throw new ServiceException("ä¸åæ ¼æ°éä¸è½ä¸ºç©º"); } // åºååæ ¼æ°é以åä¸åæ ¼å¤çè¿è¡å¯¹åºçå¤ç Assert.isTrue(qualityInspect.getQuantity().compareTo(qualityInspect.getQualifiedQuantity().add(qualityInspect.getUnqualifiedQuantity())) == 0,"è¯·æ£æ¥åæ ¼æ°éåä¸åæ ¼æ°éï¼éè¦åæ ¼æ°é+ä¸åæ ¼æ°é䏿»æ°ä¿æä¸è´"); if(qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){ // å¦æåæ ¼æ°é为空ï¼è®¾ä¸º0 if (qualityInspect.getQualifiedQuantity() == null) { qualityInspect.setQualifiedQuantity(BigDecimal.ZERO); } // 妿ä¸åæ ¼æ°é为空ï¼è®¾ä¸º0 if (qualityInspect.getUnqualifiedQuantity() == null) { qualityInspect.setUnqualifiedQuantity(BigDecimal.ZERO); } //åæ ¼ç´æ¥å ¥åº // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId()); if(qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){ //ä» æ·»å å ¥åºè®°å½ StockInventoryDto stockInventoryDto = new StockInventoryDto(); //妿æ¯éè´è´¨æ£åæ ¼å ¥åºéç¨CUSTOMIZATION_UNSTOCK_OUT,å ¶ä½åæ ¼å ¥åºéç¨QUALITYINSPECT_STOCK_IN @@ -124,6 +133,7 @@ qualityInspect.getProductModelId())); stockInventoryService.addStockInRecordOnly(stockInventoryDto); } // ä¸åæ ¼å¤ç if(qualityInspect.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){ QualityUnqualified qualityUnqualified = new QualityUnqualified(); BeanUtils.copyProperties(qualityInspect, qualityUnqualified); src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.home.dto.IncomeExpenseAnalysisDto; import com.ruoyi.purchase.vo.PurchaseReportVo; import com.ruoyi.sales.dto.SalesLedgerDto; import com.ruoyi.sales.dto.SalesTrendDto; import com.ruoyi.sales.dto.StatisticsTableDto; @@ -86,4 +87,7 @@ List<SalesTrendDto> statisticsTable(@Param("statisticsTableDto")StatisticsTableDto statisticsTableDto); IPage<SalesLedgerDto> listSalesLedgerAndShipped(Page page, @Param("ew") SalesLedgerDto salesLedgerDto); IPage<PurchaseReportVo> selectPurchaseReportVoPage(Page page, @Param("customerName") String customerName); } src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -149,6 +149,10 @@ /** * 产åç¶æ */ @TableField(exist = false) @Schema(description = "å ¥åºå®¡æ ¸ç¶æ") private String stockInApprovalStatus; // @TableField(exist = false) @Schema(description = "产åç¶æï¼1-å è¶³") private Integer approveStatus; src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -8,6 +8,10 @@ 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.account.mapper.sales.AccountInvoiceApplicationMapper; import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper; import com.ruoyi.account.pojo.sales.AccountInvoiceApplication; import com.ruoyi.account.pojo.sales.AccountSalesCollection; import com.ruoyi.basic.enums.ApplicationTypeEnum; import com.ruoyi.basic.enums.RecordTypeEnum; import com.ruoyi.basic.mapper.CustomerMapper; @@ -26,7 +30,9 @@ import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.other.mapper.TempFileMapper; import com.ruoyi.production.mapper.*; import com.ruoyi.production.mapper.ProductionProductInputMapper; import com.ruoyi.production.mapper.ProductionProductMainMapper; import com.ruoyi.production.mapper.ProductionProductOutputMapper; import com.ruoyi.production.service.ProductionProductMainService; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysUser; @@ -36,8 +42,14 @@ import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.sales.dto.*; import com.ruoyi.sales.mapper.*; import com.ruoyi.sales.pojo.*; import com.ruoyi.sales.mapper.CommonFileMapper; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.mapper.ShippingInfoMapper; import com.ruoyi.sales.pojo.CommonFile; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.pojo.ShippingInfo; import com.ruoyi.sales.service.ISalesLedgerService; import com.ruoyi.sales.vo.SalesLedgerVo; import lombok.RequiredArgsConstructor; @@ -93,6 +105,8 @@ private final QualityInspectMapper qualityInspectMapper; private final RedisTemplate<String, String> redisTemplate; private final FileUtil fileUtil; private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper; private final AccountSalesCollectionMapper accountSalesCollectionMapper; @Autowired private SysDeptMapper sysDeptMapper; @@ -263,23 +277,37 @@ @Override public List<MonthlyAmountDto> getAmountHalfYear(Integer type) { LocalDate now = LocalDate.now(); List<MonthlyAmountDto> result = new ArrayList<>(); for (int i = 5; i >= 0; i--) { YearMonth yearMonth = YearMonth.from(now.minusMonths(i)); LocalDateTime startTime = yearMonth.atDay(1).atStartOfDay(); LocalDateTime endTime = yearMonth.atEndOfMonth().atTime(23, 59, 59); LocalDate startTime = yearMonth.atDay(1); LocalDate endTime = yearMonth.atEndOfMonth(); MonthlyAmountDto dto = new MonthlyAmountDto(); dto.setMonth(yearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"))); dto.setReceiptAmount(BigDecimal.ZERO); dto.setInvoiceAmount(BigDecimal.ZERO); //忬¾éé¢ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(new LambdaQueryWrapper<AccountSalesCollection>() .between(AccountSalesCollection::getCollectionDate, startTime, endTime)); BigDecimal totalIncome = Optional.of( accountSalesCollections.stream() .map(AccountSalesCollection::getCollectionAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); dto.setReceiptAmount(totalIncome); //å¼ç¥¨éé¢ List<AccountInvoiceApplication> accountInvoiceApplications = accountInvoiceApplicationMapper.selectList(new LambdaQueryWrapper<AccountInvoiceApplication>() .eq(AccountInvoiceApplication::getStatus,1) .between(AccountInvoiceApplication::getApplyDate, startTime, endTime)); BigDecimal totalInvoiceAmount = Optional.of( accountInvoiceApplications.stream() .map(AccountInvoiceApplication::getInvoiceAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); dto.setInvoiceAmount(totalInvoiceAmount); result.add(dto); } return result; } src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
@@ -70,4 +70,15 @@ return AjaxResult.success(); } @PostMapping("/reAudit") @Log(title = "å ¥åºç®¡ç-åå®¡å ¥åº", businessType = BusinessType.UPDATE) @Operation(summary = "æ¹éåå®¡å ¥åºè®°å½") public AjaxResult reAudit(@RequestBody StockInRecordDto approveDto) { if(CollectionUtils.isEmpty(approveDto.getIds())){ return AjaxResult.error("è¯·éæ©è³å°ä¸æ¡æ°æ®"); } stockInRecordService.batchReAudit(approveDto.getIds()); return AjaxResult.success(); } } src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
@@ -40,4 +40,7 @@ @Schema(description = "è®°å½IDå表") private List<Long> ids; @Schema(description = "æºåå·") private String sourceOrderNo; } src/main/java/com/ruoyi/stock/service/StockInRecordService.java
@@ -23,4 +23,6 @@ void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto); int batchApprove(List<Long> ids, Integer approvalStatus); int batchReAudit(List<Long> ids); } src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -17,6 +17,8 @@ import com.ruoyi.stock.dto.StockInventoryDto; import com.ruoyi.stock.dto.StockUninventoryDto; import com.ruoyi.stock.execl.StockInRecordExportData; import com.ruoyi.production.mapper.ProductionOrderPickMapper; import com.ruoyi.production.pojo.ProductionOrderPick; import com.ruoyi.stock.mapper.StockInRecordMapper; import com.ruoyi.stock.mapper.StockInventoryMapper; import com.ruoyi.stock.mapper.StockUninventoryMapper; @@ -30,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.util.List; @Service @@ -39,6 +42,7 @@ private StockInRecordMapper stockInRecordMapper; private StockInventoryMapper stockInventoryMapper; private StockUninventoryMapper stockUninventoryMapper; private ProductionOrderPickMapper productionOrderPickMapper; @Override public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) { @@ -152,6 +156,32 @@ return stockUninventoryMapper.selectOne(eq); } /** * åæ»ç产éæå ¥åºçé¢æè®°å½éææ°é * @param stockInRecord å ¥åºè®°å½ */ private void rollbackFeedReturnQty(StockInRecord stockInRecord) { ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId()); if (productionOrderPick != null) { BigDecimal returnQty = productionOrderPick.getReturnQty(); if (returnQty == null) { returnQty = BigDecimal.ZERO; } BigDecimal newReturnQty = returnQty.subtract(stockInRecord.getStockInNum()); if (newReturnQty.compareTo(BigDecimal.ZERO) < 0) { newReturnQty = BigDecimal.ZERO; } productionOrderPick.setReturnQty(newReturnQty); // éæ°è®¡ç®å®é ç¨é BigDecimal actualQty = productionOrderPick.getQuantity().add( productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO) .subtract(newReturnQty); productionOrderPick.setActualQty(actualQty); productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0); productionOrderPickMapper.updateById(productionOrderPick); } } @Override @Transactional(rollbackFor = Exception.class) public int batchDeletePending(List<Long> ids) { @@ -162,6 +192,11 @@ } if (stockInRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockInRecord.getApprovalStatus())) { throw new BaseException("åªæå¾ å®¡æ¹ç¶æçè®°å½æè½å é¤,å ¥åºæ¹æ¬¡:" + stockInRecord.getInboundBatches()); } // 妿æ¯ç产éæå ¥åºï¼å 餿¶éè¦åæ»é¢æè®°å½çéææ°é if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { rollbackFeedReturnQty(stockInRecord); } } return stockInRecordMapper.deleteBatchIds(ids); @@ -186,6 +221,13 @@ } stockInRecord.setApprovalStatus(approvalStatus); stockInRecordMapper.updateById(stockInRecord); // 审æ¹é©³åæ¶ï¼å¦ææ¯ç产éæå ¥åºï¼éè¦åæ»é¢æè®°å½çéææ°é if (ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus) && StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { rollbackFeedReturnQty(stockInRecord); } // 审æ¹éè¿æ¶ï¼åºåå¢å if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) { if ("0".equals(stockInRecord.getType())) { @@ -231,4 +273,50 @@ } return ids.size(); } @Override @Transactional(rollbackFor = Exception.class) public int batchReAudit(List<Long> ids) { if (CollectionUtils.isEmpty(ids)) { throw new BaseException("è¯·éæ©è³å°ä¸æ¡æ°æ®"); } for (Long id : ids) { StockInRecord stockInRecord = stockInRecordMapper.selectById(id); if (stockInRecord == null) { throw new BaseException("å ¥åºè®°å½ä¸åå¨,æ æ³éæ°å®¡æ ¸!!!"); } // åªæé©³åç¶ææè½éæ°å®¡æ ¸ if (!ReviewStatusEnum.REJECTED.getCode().equals(stockInRecord.getApprovalStatus())) { throw new BaseException("åªæé©³åç¶æçè®°å½æè½éæ°å®¡æ ¸,å ¥åºæ¹æ¬¡:" + stockInRecord.getInboundBatches()); } // 妿æ¯ç产éæå ¥åºï¼æ¢å¤éææ°éï¼å ä¸ºé©³åæ¶å·²æ£åï¼ if (StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode().equals(stockInRecord.getRecordType())) { ProductionOrderPick productionOrderPick = productionOrderPickMapper.selectById(stockInRecord.getRecordId()); if (productionOrderPick != null) { BigDecimal returnQty = productionOrderPick.getReturnQty(); if (returnQty == null) { returnQty = BigDecimal.ZERO; } // éæ°å®¡æ ¸æ¶æ¢å¤éææ°é BigDecimal newReturnQty = returnQty.add(stockInRecord.getStockInNum()); productionOrderPick.setReturnQty(newReturnQty); // éæ°è®¡ç®å®é ç¨é BigDecimal actualQty = productionOrderPick.getQuantity().add( productionOrderPick.getFeedingQty() != null ? productionOrderPick.getFeedingQty() : BigDecimal.ZERO) .subtract(newReturnQty); productionOrderPick.setActualQty(actualQty); productionOrderPick.setReturned(newReturnQty.compareTo(BigDecimal.ZERO) > 0); productionOrderPickMapper.updateById(productionOrderPick); } } // å°ç¶ææ¹ä¸ºå¾ å®¡æ ¸ stockInRecord.setApprovalStatus(ReviewStatusEnum.PENDING_REVIEW.getCode()); stockInRecordMapper.updateById(stockInRecord); } return ids.size(); } } src/main/resources/financial-agent-prompt.txt
@@ -6,6 +6,6 @@ 2. å½ä¸ææ¬ã婿¶¦ãåºåèµéãç°éæµãé¢è¦ã驾驶è±ãæ¥æ¥å¨æ¥åºæ¯æ¶ï¼ä¼å è°ç¨å¯¹åºå·¥å ·ã 3. å·¥å ·è¿å JSON æ¶ï¼ç´æ¥è¾åºåå§ JSON å符串ï¼ä¸è¦é¢å¤å 裹 Markdownï¼ä¹ä¸è¦å¨åå追å è§£éææ¬ã 4. å½ç¨æ·é®é¢ç¼ºå°æ¶é´èå´æ¶ï¼é»è®¤ä½¿ç¨å·¥å ·å ç½®å£å¾ï¼å¦è¿30å¤©ãæ¬æãè¿90天ï¼ï¼å¹¶å¨åç»å¯æéç¨æ·è¡¥å èå´ã 5. ç¨æ·é®â为ä»ä¹å©æ¶¦ä¸éââåªä¸ªè®¢åäºæââåªä¸ªå®¢æ·æèµé±ââåªä¸ªè½¦é´/å·¥åºææ¬æé«âçé®é¢æ¶ï¼ä¼å åºäºè®¢å婿¶¦ä¸å·¥åºææ¬åæå·¥å ·ä½çã 5. ç¨æ·é®â为ä»ä¹å©æ¶¦ä¸éââåªä¸ªè®¢åäºæââåªä¸ªå®¢æ·æèµé±ââåªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«ââåªä¸ªè½¦é´/å·¥åºææ¬æé«âçé®é¢æ¶ï¼ä¼å åºäºè®¢å婿¶¦ä¸å·¥åºææ¬åæå·¥å ·ä½çã 6. åçå¿ é¡»ä½¿ç¨ä¸æï¼è¥æ°æ®ä¸è¶³ä»¥å¾åºç»è®ºï¼æç¡®æåºç¼ºå°åªäºå ³é®å段æç鿡件ã 7. ç¨æ·æå°âä»å¹´/æ¬æ/ä»å¤©/æè¿/䏿/å»å¹´âçç¸å¯¹æ¶é´æ¶ï¼å¿ é¡»ä¸¥æ ¼åºäºâå½åæ¥æâæ¢ç®ï¼ç¦æ¢èªè¡å设年份ã src/main/resources/mapper/account/AccountStatementMapper.xml
@@ -40,4 +40,39 @@ </if> ORDER BY lj.statement_month DESC </select> <select id="selectVatDtoPage" resultType="com.ruoyi.purchase.dto.VatDto"> SELECT month, jTaxAmount, xTaxAmount, (jTaxAmount - xTaxAmount) AS taxAmount FROM ( SELECT month, SUM(IF(type = 'purchase', tax_price, 0)) AS xTaxAmount, SUM(IF(type = 'sales', tax_price, 0)) AS jTaxAmount FROM ( SELECT DATE_FORMAT(issue_date, '%Y-%m') AS month, tax_price, 'sales' AS type FROM account_sales_invoice WHERE status != 1 UNION ALL SELECT DATE_FORMAT(issue_date, '%Y-%m') AS month, tax_price, 'purchase' AS type FROM account_purchase_invoice WHERE status != 1 ) AS all_data GROUP BY month ) AS TT <where> <if test="month != null"> and TT.month = #{month} </if> </where> ORDER BY TT.month </select> </mapper> src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -17,6 +17,8 @@ </select> <select id="selectPurchaseLedgerListPage" resultType="com.ruoyi.purchase.dto.PurchaseLedgerDto"> SELECT result.* FROM ( SELECT pl.id, pl.purchase_contract_number, @@ -34,9 +36,65 @@ sm.is_white, pl.approval_status, pl.payment_method, pl.remarks pl.remarks, CASE WHEN IFNULL(ls.total_product_count, 0) = 0 THEN 'å¾ å ¥åº' WHEN IFNULL(ls.full_product_count, 0) >= IFNULL(ls.total_product_count, 0) THEN 'å®å ¨å ¥åº' WHEN IFNULL(ls.approved_product_count, 0) > 0 THEN 'å ¥åºä¸' ELSE 'å¾ å ¥åº' END AS stock_in_status FROM purchase_ledger pl LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id LEFT JOIN ( SELECT product_status.sales_ledger_id, COUNT(1) AS total_product_count, SUM(CASE WHEN product_status.approved_stock_in_num > 0 THEN 1 ELSE 0 END) AS approved_product_count, SUM(CASE WHEN product_status.approved_stock_in_num >= product_status.product_quantity THEN 1 ELSE 0 END) AS full_product_count FROM ( SELECT slp.id AS sales_ledger_product_id, slp.sales_ledger_id, IFNULL(slp.quantity, 0) AS product_quantity, IFNULL(approved_qty.approved_stock_in_num, 0) AS approved_stock_in_num FROM sales_ledger_product slp LEFT JOIN ( SELECT rel.sales_ledger_product_id, IFNULL(SUM(rel.stock_in_num), 0) AS approved_stock_in_num FROM ( SELECT slp.id AS sales_ledger_product_id, sir.stock_in_num FROM stock_in_record sir INNER JOIN sales_ledger_product slp ON slp.type = 2 AND TRIM(sir.record_type) = '7' AND sir.record_id = slp.sales_ledger_id AND ( (sir.batch_no IS NOT NULL AND sir.batch_no LIKE CONCAT('%-', slp.id)) OR (sir.batch_no IS NULL AND sir.product_model_id = slp.product_model_id) ) WHERE sir.approval_status = 1 UNION ALL SELECT slp.id AS sales_ledger_product_id, sir.stock_in_num FROM stock_in_record sir INNER JOIN quality_inspect qi ON TRIM(sir.record_type) = '10' AND sir.record_id = qi.id INNER JOIN sales_ledger_product slp ON slp.type = 2 AND slp.sales_ledger_id = qi.purchase_ledger_id AND slp.product_model_id = qi.product_model_id WHERE sir.approval_status = 1 ) rel GROUP BY rel.sales_ledger_product_id ) approved_qty ON approved_qty.sales_ledger_product_id = slp.id WHERE slp.type = 2 ) product_status GROUP BY product_status.sales_ledger_id ) ls ON ls.sales_ledger_id = pl.id <where> <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''"> AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%') @@ -66,7 +124,11 @@ AND pl.approval_status = #{c.approvalStatus} </if> </where> ORDER BY pl.entry_date DESC ) result <if test="c.stockInStatus != null and c.stockInStatus != ''"> WHERE result.stock_in_status = #{c.stockInStatus} </if> ORDER BY result.entry_date DESC </select> <select id="selectTotalPurchaseAmount" resultType="java.math.BigDecimal"> src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -121,5 +121,21 @@ </if> order by sl.execution_date desc </select> <select id="selectPurchaseReportVoPage" resultType="com.ruoyi.purchase.vo.PurchaseReportVo"> select sl.sales_contract_no customerContractNo, c.customer_name, sl.project_name, sl.contract_amount contractAmount, pl.contract_amount purchaseAmount, sl.contract_amount-pl.contract_amount balance, (sl.contract_amount-pl.contract_amount)/sl.contract_amount balanceRatio from sales_ledger sl left join purchase_ledger pl on sl.id = pl.sales_ledger_id left join customer c on sl.customer_id = c.id where 1=1 <if test="customerName != null and customerName != '' "> and c.customer_name like concat('%',#{customerName},'%') </if> </select> </mapper> src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -38,7 +38,13 @@ WHEN IFNULL(t3.shipped_quantity, 0) = 0 THEN 'å¾ åè´§' WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN 'é¨ååè´§' ELSE 'å·²åè´§' END as shippingStatus END as shippingStatus, CASE WHEN T1.type != 2 THEN NULL WHEN IFNULL(t4.approved_stock_in_num, 0) <= 0 THEN 'å¾ å ¥åº' WHEN IFNULL(t4.approved_stock_in_num, 0) >= IFNULL(T1.quantity, 0) THEN 'å®å ¨å ¥åº' ELSE 'å ¥åºä¸' END AS stock_in_approval_status FROM sales_ledger_product T1 LEFT JOIN ( @@ -53,6 +59,39 @@ where si.status != 'å®¡æ ¸æç»' GROUP BY sales_ledger_product_id ) t3 ON t3.sales_ledger_product_id = T1.id LEFT JOIN ( SELECT rel.sales_ledger_product_id, IFNULL(SUM(rel.stock_in_num), 0) AS approved_stock_in_num FROM ( SELECT slp.id AS sales_ledger_product_id, sir.stock_in_num FROM stock_in_record sir INNER JOIN sales_ledger_product slp ON slp.type = 2 AND TRIM(sir.record_type) = '7' AND sir.record_id = slp.sales_ledger_id AND ( (sir.batch_no IS NOT NULL AND sir.batch_no LIKE CONCAT('%-', slp.id)) OR (sir.batch_no IS NULL AND sir.product_model_id = slp.product_model_id) ) WHERE sir.approval_status = 1 UNION ALL SELECT slp.id AS sales_ledger_product_id, sir.stock_in_num FROM stock_in_record sir INNER JOIN quality_inspect qi ON TRIM(sir.record_type) = '10' AND sir.record_id = qi.id INNER JOIN sales_ledger_product slp ON slp.type = 2 AND slp.sales_ledger_id = qi.purchase_ledger_id AND slp.product_model_id = qi.product_model_id WHERE sir.approval_status = 1 ) rel GROUP BY rel.sales_ledger_product_id ) t4 ON t4.sales_ledger_product_id = T1.id left join product_model pm ON T1.product_model_id = pm.id left join product p ON pm.product_id = p.id <where> src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -19,11 +19,96 @@ p.product_name as product_name, pm.model, pm.unit, u.nick_name as createBy u.nick_name as createBy, CASE WHEN #{params.topParentProductId} = 278 AND TRIM(sir.record_type) = '7' THEN COALESCE(pl_by_product.purchase_contract_number, pl_direct.purchase_contract_number) WHEN #{params.topParentProductId} = 278 AND TRIM(sir.record_type) = '10' THEN pl_by_quality.purchase_contract_number WHEN #{params.topParentProductId} = 276 THEN CASE WHEN TRIM(sir.record_type) IN ('14', '15') THEN sl_return.sales_contract_no WHEN TRIM(sir.record_type) IN ('2', '5') THEN COALESCE(po_sales_main.sales_contract_no, po_main.nps_no) WHEN TRIM(sir.record_type) = '6' THEN COALESCE(po_sales_qi.sales_contract_no, po_qi.nps_no) WHEN TRIM(sir.record_type) IN ('4', '11') THEN COALESCE(po_sales_uq.sales_contract_no, po_uq.nps_no) WHEN TRIM(sir.record_type) IN ('20', '22') THEN COALESCE(po_sales_pick.sales_contract_no, po_pick.nps_no) ELSE NULL END ELSE NULL END AS sourceOrderNo FROM stock_in_record as sir LEFT JOIN product_model as pm on sir.product_model_id = pm.id LEFT JOIN product as p on pm.product_id = p.id LEFT JOIN sys_user as u on sir.create_user = u.user_id LEFT JOIN quality_inspect as qi_purchase on TRIM(sir.record_type) = '10' and sir.record_id = qi_purchase.id LEFT JOIN sales_ledger_product as slp on TRIM(sir.record_type) = '7' and slp.id = sir.record_id and slp.type = 2 LEFT JOIN purchase_ledger as pl_by_product on TRIM(sir.record_type) = '7' and pl_by_product.id = slp.sales_ledger_id LEFT JOIN purchase_ledger as pl_direct on TRIM(sir.record_type) = '7' and pl_direct.id = sir.record_id LEFT JOIN purchase_ledger as pl_by_quality on TRIM(sir.record_type) = '10' and pl_by_quality.id = qi_purchase.purchase_ledger_id LEFT JOIN production_product_main as ppm_main on TRIM(sir.record_type) IN ('2', '5') and sir.record_id = ppm_main.id LEFT JOIN production_operation_task as pot_main on ppm_main.production_operation_task_id = pot_main.id LEFT JOIN production_order as po_main on pot_main.production_order_id = po_main.id LEFT JOIN ( select po2.id as production_order_id, group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no from production_order po2 left join production_plan pp2 on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0 left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id group by po2.id ) as po_sales_main on po_sales_main.production_order_id = po_main.id LEFT JOIN quality_inspect as qi_prod on TRIM(sir.record_type) = '6' and sir.record_id = qi_prod.id LEFT JOIN production_product_main as ppm_qi on qi_prod.product_main_id = ppm_qi.id LEFT JOIN production_operation_task as pot_qi on ppm_qi.production_operation_task_id = pot_qi.id LEFT JOIN production_order as po_qi on pot_qi.production_order_id = po_qi.id LEFT JOIN ( select po2.id as production_order_id, group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no from production_order po2 left join production_plan pp2 on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0 left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id group by po2.id ) as po_sales_qi on po_sales_qi.production_order_id = po_qi.id LEFT JOIN quality_unqualified as qu on TRIM(sir.record_type) IN ('4', '11') and sir.record_id = qu.id LEFT JOIN quality_inspect as qi_uq on qu.inspect_id = qi_uq.id LEFT JOIN production_product_main as ppm_uq on qi_uq.product_main_id = ppm_uq.id LEFT JOIN production_operation_task as pot_uq on ppm_uq.production_operation_task_id = pot_uq.id LEFT JOIN production_order as po_uq on pot_uq.production_order_id = po_uq.id LEFT JOIN ( select po2.id as production_order_id, group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no from production_order po2 left join production_plan pp2 on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0 left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id group by po2.id ) as po_sales_uq on po_sales_uq.production_order_id = po_uq.id LEFT JOIN production_order_pick as pop on TRIM(sir.record_type) IN ('20', '22') and sir.record_id = pop.id LEFT JOIN production_order as po_pick on pop.production_order_id = po_pick.id LEFT JOIN ( select po2.id as production_order_id, group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no from production_order po2 left join production_plan pp2 on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0 left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id group by po2.id ) as po_sales_pick on po_sales_pick.production_order_id = po_pick.id LEFT JOIN return_sale_product as rsp on TRIM(sir.record_type) IN ('14', '15') and sir.record_id = rsp.id LEFT JOIN return_management as rm on rsp.return_management_id = rm.id LEFT JOIN shipping_info as si_return on rm.shipping_id = si_return.id LEFT JOIN sales_ledger as sl_return on si_return.sales_ledger_id = sl_return.id <where> <if test="params.timeStr != null and params.timeStr != ''"> and sir.create_time like concat('%',#{params.timeStr},'%')