From 37e8d3271fdc473ab9f756a3445f595d3babeab7 Mon Sep 17 00:00:00 2001
From: jenkins <jenkins@example.com>
Date: 星期五, 22 五月 2026 20:35:58 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New_pro' into dev_pro_河南鹤壁

---
 doc/20260522_采购台账入库状态_销售产品入库审核状态前端联调文档.md                                             |  127 +++
 src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java                    |    3 
 src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java                  |    4 
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java           |   24 
 src/main/resources/mapper/account/AccountStatementMapper.xml                          |   35 +
 src/main/resources/mapper/sales/SalesLedgerMapper.xml                                 |   16 
 src/main/java/com/ruoyi/project/system/service/ISysUserService.java                   |    7 
 src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java           |    7 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java          |    7 
 src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java                   |   14 
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                            |    4 
 src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml                           |  162 +++-
 src/main/java/com/ruoyi/stock/service/StockInRecordService.java                       |    2 
 src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java              |   88 ++
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java                        |  329 ++++++---
 src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml        |    2 
 src/main/java/com/ruoyi/stock/controller/StockInRecordController.java                 |   11 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                          |   41 +
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java          |   32 +
 src/main/java/com/ruoyi/project/system/controller/SysUserController.java              |    5 
 src/main/java/com/ruoyi/account/controller/AccountingController.java                  |   24 
 src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java           |   26 
 src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java                           |    4 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                |   52 +
 src/main/resources/financial-agent-prompt.txt                                         |    2 
 src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java                     |   22 
 doc/20260522_财务助手提问优化前端变更文档.md                                                        |   59 +
 doc/20260522_首页财务接口升级前端变更文档.md                                                        |  120 +++
 src/main/java/com/ruoyi/purchase/dto/VatDto.java                                      |   17 
 src/main/java/com/ruoyi/account/service/AccountingService.java                        |   19 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |    2 
 src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java                        |   19 
 src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java                           |    2 
 doc/20260522_StockInRecord列表源单号前端联调文档_276补充.md                                        |   65 ++
 doc/20260522_StockInRecord列表源单号前端联调文档.md                                              |   75 ++
 src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java                             |   44 +
 src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java                          |   66 ++
 src/main/resources/mapper/stock/StockInRecordMapper.xml                               |   87 ++
 src/main/java/com/ruoyi/quality/pojo/QualityInspect.java                              |    5 
 src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml           |    2 
 src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java                               |    3 
 src/main/resources/mapper/quality/QualityInspectMapper.xml                            |   43 
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                |    2 
 /dev/null                                                                             |   39 -
 src/main/java/com/ruoyi/quality/controller/QualityInspectController.java              |    3 
 src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java               |  189 +++++
 46 files changed, 1,599 insertions(+), 312 deletions(-)

diff --git "a/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..56d1570
--- /dev/null
+++ "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,75 @@
+# StockInRecord 鍒楄〃婧愬崟鍙峰墠绔仈璋冩枃妗�
+
+鏇存柊鏃堕棿锛�2026-05-22  
+閫傜敤鎺ュ彛锛歚GET /stockInRecord/listPage`
+
+## 1. 鍙樻洿璇存槑
+
+鏈瀵瑰叆搴撶鐞嗗垪琛ㄦ帴鍙e鍔犺繑鍥炲瓧娈� `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` 绛夛級涓嶅彈褰卞搷銆�
diff --git "a/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md" "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md"
new file mode 100644
index 0000000..93d9b25
--- /dev/null
+++ "b/doc/20260522_StockInRecord\345\210\227\350\241\250\346\272\220\345\215\225\345\217\267\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243_276\350\241\245\345\205\205.md"
@@ -0,0 +1,65 @@
+# StockInRecord 鍒楄〃婧愬崟鍙峰墠绔仈璋冩枃妗o紙`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`锛氫粛鎸夐噰璐摼璺繑鍥為噰璐悎鍚屽彿銆�  
diff --git "a/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..ad4656e
--- /dev/null
+++ "b/doc/20260522_\350\264\242\345\212\241\345\212\251\346\211\213\346\217\220\351\227\256\344\274\230\345\214\226\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,59 @@
+# 璐㈠姟鍔╂墜鎻愰棶浼樺寲鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-22  
+閫傜敤妯″潡锛氳储鍔℃櫤鑳藉姪鎵嬶紙`/financial-ai`锛�
+
+## 1. 鑳屾櫙
+
+褰撳墠棣栭〉璐㈠姟鍔╂墜蹇嵎鎻愰棶涓猴細
+
+1. `鐢熸垚鏈懆缁忚惀鍛ㄦ姤`
+2. `涓轰粈涔堝埄娑︿笅闄峘
+3. `鍝釜瀹㈡埛鏈�璧氶挶`
+
+闂鐐癸細
+
+- 绗� 3 鏉¢棶娉曞湪閮ㄥ垎鍦烘櫙涓嬫剰鍥惧懡涓笉绋冲畾锛屽鏄撹蛋鏅�氭枃鏈洖绛旓紝瀵艰嚧鍥捐〃閾炬帴浠ュ師濮� Markdown 鏂囨湰灞曠ず锛堝 `![...](https://local/generate_chart?options=...)`锛夈��
+- 蹇嵎鎻愰棶缂哄皯鏃堕棿鑼冨洿鍜屽垎鏋愮洰鏍囷紝缁撴灉绋冲畾鎬т笌鍙В閲婃�ц緝寮便��
+
+## 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. 瑙f瀽 `options` 鍙傛暟骞惰浆鎹负 ECharts `option` 鍚庢覆鏌撳浘琛ㄧ粍浠躲��
+3. 瑙f瀽澶辫触鏃朵笉灞曠ず鍘熷闀块摼鎺ユ枃鏈紝灞曠ず缁熶竴绌烘�佹彁绀恒��
+
+## 5. 鑱旇皟鍥炲綊娓呭崟
+
+1. 鐐瑰嚮蹇嵎鎻愰棶 `鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級`  
+   - 鏍¢獙杩斿洖 `type=financial_operation_report`锛屽苟姝e父娓叉煋鎽樿/寤鸿/鍥捐〃銆�
+2. 鐐瑰嚮蹇嵎鎻愰棶 `鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜`  
+   - 鏍¢獙杩斿洖 `type=financial_order_profit_analysis`锛屽苟灞曠ず浜忔崯璁㈠崟涓庡鎴峰埄娑︽帓琛屻��
+3. 鐐瑰嚮蹇嵎鎻愰棶 `杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂榒  
+   - 鏍¢獙杩斿洖 `type=financial_order_profit_analysis`锛宍summary.topCustomerByProfit` 鏈夊�笺��
+4. 鎵嬪伐杈撳叆 `鍝釜瀹㈡埛鏈�璧氶挶`銆乣鍝釜瀹㈡埛鍒╂鼎鏈�楂榒  
+   - 鏍¢獙浠嶅懡涓� `financial_order_profit_analysis`锛屼笉鍐嶅嚭鐜板師濮嬪浘琛� Markdown 閾炬帴鐩村嚭銆�
diff --git "a/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md" "b/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..ae212fc
--- /dev/null
+++ "b/doc/20260522_\351\207\207\350\264\255\345\217\260\350\264\246\345\205\245\345\272\223\347\212\266\346\200\201_\351\224\200\345\224\256\344\272\247\345\223\201\345\205\245\345\272\223\345\256\241\346\240\270\347\212\266\346\200\201\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243.md"
@@ -0,0 +1,127 @@
+# 閲囪喘鍏ュ簱鐘舵�佸墠绔仈璋冩枃妗�
+鏇存柊鏃堕棿锛�2026-05-22  
+閫傜敤鐗堟湰锛氭湰娆″悗绔彉鏇村悗
+
+## 1. 鍙樻洿鑼冨洿
+
+1. `GET /purchaseLedger/listPage`  
+   - 鏂板鏌ヨ鏉′欢锛歚stockInStatus`锛堝叆搴撶姸鎬侊級
+   - 鏂板杩斿洖瀛楁锛歚stockInStatus`锛堝叆搴撶姸鎬侊級
+2. `GET /salesLedgerProduct/list`  
+   - 鏂板杩斿洖瀛楁锛歚stockInApprovalStatus`锛堟瘡涓骇鍝佺殑鍏ュ簱瀹℃牳鐘舵�侊級
+
+---
+
+## 2. 鍏ュ簱鐘舵�佹灇涓撅紙涓ゆ帴鍙d竴鑷达級
+
+- `寰呭叆搴揱
+- `鍏ュ簱涓璥
+- `瀹屽叏鍏ュ簱`
+
+璇存槑锛氬墠绔瓫閫夊�艰鐩存帴浣跨敤浠ヤ笂涓枃鏋氫妇鍊笺��
+
+---
+
+## 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`锛氬簲姝e父杩斿洖鍏ㄩ儴鏁版嵁锛屽苟甯� `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`銆�
diff --git "a/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md" "b/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..532eba7
--- /dev/null
+++ "b/doc/20260522_\351\246\226\351\241\265\350\264\242\345\212\241\346\216\245\345\217\243\345\215\207\347\272\247\345\211\215\347\253\257\345\217\230\346\233\264\346\226\207\346\241\243.md"
@@ -0,0 +1,120 @@
+# 棣栭〉璐㈠姟鎺ュ彛鍗囩骇鍓嶇鍙樻洿鏂囨。
+
+鏇存柊鏃堕棿锛�2026-05-22  
+閫傜敤妯″潡锛氶椤碉紙`/home`锛�
+
+## 1. 鍙樻洿姒傝
+
+鏈涓� **鍏煎寮忓崌绾�**锛屾帴鍙� URL銆佽姹傚弬鏁般�佽繑鍥炲瓧娈典繚鎸佷笉鍙樸��  
+涓昏鍙樻洿鏄椤佃储鍔℃暟鎹粠鍗犱綅/鍗婃垚鍝侀�昏緫锛屽垏鎹负鎸夎储鍔$湡瀹炴暟鎹彛寰勮绠椼��
+
+娑夊強鎺ュ彛锛�
+
+1. `GET /home/statisticsReceivablePayable`
+2. `GET /home/monthlyIncome`
+3. `GET /home/monthlyExpenditure`
+
+## 2. 鍙傛暟璇存槑锛堟棤鏂板锛�
+
+### 2.1 `GET /home/statisticsReceivablePayable`
+
+- `type`锛歚1` 鏈懆锛宍2` 鏈湀锛宍3` 鏈搴︼紙榛樿 `1`锛�
+
+### 2.2 `GET /home/monthlyIncome`
+
+- 鏃犲弬鏁�
+
+### 2.3 `GET /home/monthlyExpenditure`
+
+- 鏃犲弬鏁�
+
+## 3. 杩斿洖瀛楁鍙e緞鍙樻洿
+
+### 3.1 搴旀敹搴斾粯缁熻 `statisticsReceivablePayable`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `receivableMoney`
+- `payableMoney`
+- `advanceMoney`
+- `prepayMoney`
+
+鏂板彛寰勶細
+
+- `receivableMoney = max(閿�鍞悎鍚岄噾棰濆悎璁� - 鏀舵閲戦鍚堣, 0)`
+- `payableMoney = max(閲囪喘鍚堝悓閲戦鍚堣 - 浠樻閲戦鍚堣, 0)`
+- `advanceMoney = 鏀舵閲戦鍚堣`
+- `prepayMoney = 浠樻閲戦鍚堣`
+
+浠ヤ笂閲戦鍧囨寜 `type` 瀵瑰簲鏃堕棿鑼冨洿缁熻锛屼繚鐣欎袱浣嶅皬鏁般��
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+  "receivableMoney": 128000.00,
+  "payableMoney": 76000.00,
+  "advanceMoney": 42000.00,
+  "prepayMoney": 31000.00
+}
+```
+
+### 3.2 鏈堝害鏀跺叆 `monthlyIncome`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `monthlyIncome`
+- `collectionRate`
+- `overdueNum`
+- `overdueRate`
+
+鏂板彛寰勶細
+
+- `monthlyIncome`锛氬綋鏈堟敹娆惧悎璁�
+- `collectionRate`锛歚褰撴湀鏀舵鍚堣 / 褰撴湀閿�鍞悎鍚岄噾棰濆悎璁� * 100`
+- `overdueNum`锛氬巻鍙插簲鏀跺璐﹀崟锛坄account_statement.account_type=1`锛変腑锛屾棭浜庡綋鏈堜笖 `closing_balance > 0` 鐨勬暟閲�
+- `overdueRate`锛歚overdueNum / 鍘嗗彶搴旀敹瀵硅处鍗曟�绘暟 * 100`
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+  "monthlyIncome": 89500.00,
+  "collectionRate": "62.80",
+  "overdueNum": 4,
+  "overdueRate": "18.18"
+}
+```
+
+### 3.3 鏈堝害鏀嚭 `monthlyExpenditure`
+
+杩斿洖瀛楁涓嶅彉锛�
+
+- `monthlyExpenditure`
+- `paymentRate`
+- `grossProfit`
+- `profitMarginRate`
+
+鏂板彛寰勶細
+
+- `monthlyExpenditure`锛氬綋鏈堜粯娆惧悎璁�
+- `paymentRate`锛歚褰撴湀浠樻鍚堣 / 褰撴湀閲囪喘鍚堝悓閲戦鍚堣 * 100`
+- `grossProfit`锛歚褰撴湀鏀舵鍚堣 - 褰撴湀浠樻鍚堣`
+- `profitMarginRate`锛歚grossProfit / 褰撴湀鏀舵鍚堣 * 100`
+
+杩斿洖绀轰緥锛�
+
+```json
+{
+  "monthlyExpenditure": 73400.00,
+  "paymentRate": "57.34",
+  "grossProfit": 16100.00,
+  "profitMarginRate": "17.99"
+}
+```
+
+## 4. 鍓嶇鑱旇皟璇存槑
+
+1. 鍓嶇瀛楁鏄犲皠鏃犻渶璋冩暣锛屽彲鐩存帴娌跨敤鐜版湁瑙f瀽閫昏緫銆�  
+2. 鐧惧垎姣斿瓧娈典粛涓轰笉甯� `%` 鐨勫瓧绗︿覆锛屽墠绔闇�灞曠ず `%` 璇风户缁墠绔嫾鎺ャ��  
+3. 鏈鍚庣杩斿洖鍊肩敱鐪熷疄璐㈠姟鏁版嵁椹卞姩锛屽缓璁噸鐐瑰洖褰掑崱鐗囨眹鎬讳笌瓒嬪娍鍥剧殑鏁板�艰仈鍔ㄣ��  
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java
deleted file mode 100644
index 5af0ca6..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃
- */
-
-@Data
-public class AccountDto implements Serializable {
-
-
-    /**
-     * 鎬绘敹鍏�
-     */
-    private BigDecimal totalIncome;
-
-    /**
-     * 鍚勭被鍨嬫敹鍏ラ噾棰�(閿�鍞敹鍏ワ紝鏈嶅姟鏀跺叆锛屽叾浠栨敹鍏�)
-     */
-    private List<AccountDto2> incomeType;
-
-
-    /**
-     * 鏀跺叆绗旀暟
-     */
-    private Long incomeNumber;
-
-    /**
-     * 鎬绘敮鍑�
-     */
-    private BigDecimal totalExpense;
-
-
-    /**
-     * 鍚勭被鍨嬫敮鍑洪噾棰�(鍔炲叕鐢ㄥ搧锛屽憳宸ュ伐璧勶紝宸梾璐癸紝璁惧璐圭敤锛屽叾浠�)
-     */
-    private List<AccountDto2> expenseType;
-
-    /**
-     * 鏀嚭绗旀暟
-     */
-    private Long expenseNumber;
-
-    /**
-     * 鍑�鏀跺叆
-     */
-    private BigDecimal netRevenue;
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java
deleted file mode 100644
index 7c4e9e5..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto2.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃(绫诲瀷)
- */
-
-@Data
-public class AccountDto2 implements Serializable {
-
-
-    /**
-     * 绫诲瀷
-     */
-    private String typeName;
-
-
-    /**
-     * 鐧惧垎鍗犳瘮
-     */
-    private BigDecimal proportion;
-
-
-
-    /**
-     * 閲戦
-     */
-    private BigDecimal account;
-
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java b/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java
deleted file mode 100644
index 117fa77..0000000
--- a/src/main/java/com/ruoyi/account/bean/dto/AccountDto3.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ruoyi.account.bean.dto;
-
-import lombok.Data;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 璐㈠姟绠$悊--璐㈠姟鎶ヨ〃(绫诲瀷)
- */
-
-@Data
-public class AccountDto3 implements Serializable {
-
-
-    /**
-     * 绫诲瀷
-     */
-    private String typeName;
-
-
-    /**
-     * 鐧惧垎鍗犳瘮
-     */
-    private BigDecimal proportion;
-
-
-
-    /**
-     * 閲戦
-     */
-    private List<BigDecimal> account;
-
-
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java b/src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
similarity index 70%
rename from src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java
rename to src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
index 5e89162..8d4bf31 100644
--- a/src/main/java/com/ruoyi/account/bean/dto/ReportDateDto.java
+++ b/src/main/java/com/ruoyi/account/bean/dto/AccountReportDto.java
@@ -1,17 +1,16 @@
 package com.ruoyi.account.bean.dto;
 
 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.time.LocalDate;
 
-/**
- * @author :yys
- * @date : 2026/1/16 16:57
- */
+
 @Data
-public class ReportDateDto {
+@Schema(name = "AccountReportDto", description = "璐㈠姟鎶ヨ〃--鏃ユ湡鍙傛暟")
+public class AccountReportDto {
 
     /**
      * 寮�濮嬫椂闂�
@@ -26,15 +25,5 @@
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate entryDateEnd;
-
-    /**
-     * 寮�濮嬫湀浠�
-     */
-    private Integer startMonth;
-
-    /**
-     * 缁撴潫鏈堜唤
-     */
-    private Integer endMonth;
 
 }
diff --git a/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java b/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
new file mode 100644
index 0000000..f7b39d8
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
@@ -0,0 +1,66 @@
+package com.ruoyi.account.bean.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+@Data
+@Schema(name = "AccountReportVo", description = "璐㈠姟鎶ヨ〃--杩斿洖鍙傛暟")
+public class AccountReportVo {
+
+    @Schema(description = "鎬昏惀鏀�")
+    private BigDecimal totalIncome;
+
+    @Schema(description = "鎬绘敮鍑�")
+    private BigDecimal totalExpense;
+
+    @Schema(description = "搴旀敹璐︽")
+    private BigDecimal accountsReceivable;
+
+    @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;
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/account/controller/AccountingController.java b/src/main/java/com/ruoyi/account/controller/AccountingController.java
index 4688942..9eeb208 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountingController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountingController.java
@@ -1,12 +1,16 @@
 package com.ruoyi.account.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.service.impl.AccountingServiceImpl;
+import com.ruoyi.account.bean.dto.AccountReportDto;
+import com.ruoyi.account.service.AccountingService;
+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 io.swagger.v3.oas.annotations.tags.Tag;
+import com.ruoyi.framework.web.domain.R;
 import io.swagger.v3.oas.annotations.Operation;
-import lombok.AllArgsConstructor;
+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.RequestParam;
@@ -19,11 +23,11 @@
 @Tag(name = "浼氳鏍哥畻")
 @RestController
 @RequestMapping("/accounting")
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class AccountingController extends BaseController {
 
 
-    private AccountingServiceImpl accountingService;
+    private final AccountingService accountingService;
 
     @Operation(summary = "鎬昏")
     @GetMapping("/total")
@@ -43,4 +47,14 @@
         return accountingService.calculateDepreciation(page,year);
     }
 
+    /*****************************************璐㈠姟鎶ヨ〃******************************************************************************/
+
+    @GetMapping("/accountStatementDetailsByMonth")
+    @Log(title = "璐㈠姟鎶ヨ〃", businessType = BusinessType.OTHER)
+    @Operation(summary = "璐㈠姟鎶ヨ〃")
+    public R getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) {
+        return R.ok(accountingService.getAccountStatementDetailsByMonth(accountReportDto));
+    }
+
+
 }
diff --git a/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java b/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
index 307cf1a..89730cb 100644
--- a/src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/account/service/AccountingService.java b/src/main/java/com/ruoyi/account/service/AccountingService.java
new file mode 100644
index 0000000..6190dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/account/service/AccountingService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.account.service;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.AccountReportDto;
+import com.ruoyi.account.bean.vo.AccountReportVo;
+import com.ruoyi.framework.web.domain.AjaxResult;
+
+public interface AccountingService {
+
+    AjaxResult total(Integer year);
+
+    AjaxResult deviceTypeDistribution(Integer year);
+
+    AjaxResult calculateDepreciation(Page page, Integer year);
+
+    AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto);
+
+}
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
index 01f5687..f42599a 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -3,25 +3,47 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.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;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
+import com.ruoyi.account.service.AccountingService;
 import com.ruoyi.device.mapper.DeviceLedgerMapper;
 import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.framework.web.domain.AjaxResult;
 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;
@@ -33,13 +55,21 @@
 @Service
 @Slf4j
 @RequiredArgsConstructor
-public class AccountingServiceImpl {
+public class AccountingServiceImpl implements AccountingService {
 
     private final DeviceLedgerMapper deviceLedgerMapper;
     private final CustomStorageMapper customStorageMapper;
     private final ProcurementRecordMapper procurementRecordMapper;
     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
     public AjaxResult total(Integer year) {
         Map<String,Object> map = new HashMap<>();
         map.put("deprAmount",0); // 鎶樻棫閲戦
@@ -233,6 +263,7 @@
         return totalDepreciation.setScale(2, BigDecimal.ROUND_HALF_UP);
     }
 
+    @Override
     public AjaxResult deviceTypeDistribution(Integer year) {
         // 2. 缁勮杩斿洖VO
        DeviceTypeDistributionVO vo = new DeviceTypeDistributionVO();
@@ -256,6 +287,7 @@
         return AjaxResult.success(vo);
     }
 
+    @Override
     public AjaxResult calculateDepreciation(Page page, Integer year) {
         LambdaQueryWrapper<DeviceLedger> deviceLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>();
         deviceLedgerLambdaQueryWrapper.like(DeviceLedger::getCreateTime,year)
@@ -267,4 +299,159 @@
         }
         return AjaxResult.success(deviceLedgerIPage);
     }
+
+    @Override
+    public AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) {
+        AccountReportVo accountReportVo = new AccountReportVo();
+        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;
+    }
 }
diff --git a/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
index c1f349c..9afadff 100644
--- a/src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
+++ b/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("鏈勾", "")
diff --git a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java b/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
index a16390c..4f1509b 100644
--- a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
+++ b/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;
 
 }
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index c21def5..d3c21a2 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,8 +3,20 @@
 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.purchase.AccountPurchasePayment;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.basic.mapper.CustomerMapper;
@@ -25,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;
@@ -41,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;
@@ -67,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;
 
@@ -104,6 +124,7 @@
 
     private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
     private final AccountSalesCollectionMapper accountSalesCollectionMapper;
+    private final AccountStatementMapper accountStatementMapper;
 
     private final ProductionAccountMapper productionAccountMapper;
 
@@ -407,43 +428,33 @@
      */
     @Override
     public StatisticsReceivablePayableDto statisticsReceivablePayable(Integer type) {
-        StatisticsReceivablePayableDto statisticsReceivablePayableDto = new StatisticsReceivablePayableDto();
-        LocalDate today = LocalDate.now();
-        LocalDate startDate = null;
-        LocalDate endDate = null;
-        switch (type) {
-            case 1:
-                // 鑾峰彇鏈懆鍛ㄤ竴
-                startDate = today.with(DayOfWeek.MONDAY);
-                // 鑾峰彇鏈懆鍛ㄦ棩
-                endDate = today.with(DayOfWeek.SUNDAY);
-                break;
-            case 2:
-                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
-                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
-                break;
-            case 3:
-                Month currentMonth = today.getMonth();
-                Month firstMonthOfQuarter = currentMonth.firstMonthOfQuarter();
-                Month lastMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
+        StatisticsReceivablePayableDto dto = new StatisticsReceivablePayableDto();
+        LocalDate[] range = resolveFinanceRange(type);
+        LocalDate startDate = range[0];
+        LocalDate endDate = range[1];
 
-                startDate = today.withMonth(firstMonthOfQuarter.getValue())
-                        .with(TemporalAdjusters.firstDayOfMonth());
-                endDate = today.withMonth(lastMonthOfQuarter.getValue())
-                        .with(TemporalAdjusters.lastDayOfMonth());
-                break;
-        }
-        // 搴旀敹
+        //閿�鍞嚭搴�
+        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);
 
-        // 搴斾粯
-
-        // 棰勬敹
-
-        // 棰勪粯
-
-
-
-        return statisticsReceivablePayableDto;
+        //搴旀敹閲戦=閿�鍞嚭搴�-閿�鍞��璐�
+        dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(salesReturnAmount))));
+        //搴斾粯閲戦=閲囪喘鍏ュ簱-閲囪喘閫�璐�
+        dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(purchaseReturnAmount))));
+        //鏀舵閲戦=鏀舵鍗�
+        dto.setAdvanceMoney(scaleMoney(advanceMoney));
+        //浠樻閲戦=浠樻鍗�
+        dto.setPrepayMoney(scaleMoney(prepayMoney));
+        return dto;
     }
 
     public static <T> BigDecimal sumAmount(List<T> list, java.util.function.Function<T, BigDecimal> amountExtractor) {
@@ -1252,102 +1263,55 @@
     @Override
     public MonthlyIncomeDto monthlyIncome() {
         MonthlyIncomeDto dto = new MonthlyIncomeDto();
-        LocalDate now = LocalDate.now();
-        YearMonth currentMonth = YearMonth.from(now);
-        LocalDateTime startOfMonth = currentMonth.atDay(1).atStartOfDay();
-        LocalDateTime endOfMonth = currentMonth.atEndOfMonth().atTime(23, 59, 59);
-
-        LambdaQueryWrapper<SalesLedgerProduct> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(SalesLedgerProduct::getType, 1);
-        wrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
-        wrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
-        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(wrapper);
-
-        if (CollectionUtils.isEmpty(products)) {
-            return dto;
-        }
-
+        LocalDate today = LocalDate.now();
+        YearMonth currentMonth = YearMonth.from(today);
+        LocalDate startDate = currentMonth.atDay(1);
+        LocalDate endDate = currentMonth.atEndOfMonth();
+        //鏀舵
+        BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate);
+        //閿�鍞嚭搴�
+        BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate);
+        //閿�鍞��璐�
+        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(overdueAmount);
+        dto.setOverdueRate(overdueRate);
         return dto;
     }
 
+    @Override
     public MonthlyExpenditureDto monthlyExpenditure() {
-
         MonthlyExpenditureDto dto = new MonthlyExpenditureDto();
+        LocalDate today = LocalDate.now();
+        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);
 
-        // 褰撴湀鏃堕棿鑼冨洿
-        LocalDate now = LocalDate.now();
-        YearMonth currentMonth = YearMonth.from(now);
-        LocalDateTime startOfMonth = currentMonth.atDay(1).atStartOfDay();
-        LocalDateTime endOfMonth = currentMonth.atEndOfMonth().atTime(23, 59, 59);
-
-        // 閲囪喘鍙拌处锛坱ype = 2锛�
-        LambdaQueryWrapper<SalesLedgerProduct> purchaseWrapper = new LambdaQueryWrapper<>();
-        purchaseWrapper.eq(SalesLedgerProduct::getType, 2);
-        purchaseWrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
-        purchaseWrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
-        List<SalesLedgerProduct> purchaseProducts = salesLedgerProductMapper.selectList(purchaseWrapper);
-
-        BigDecimal rawMaterialCost = BigDecimal.ZERO; // 鍘熸潗鏂欐垚鏈�
-        BigDecimal paidAmount = BigDecimal.ZERO; // 宸蹭粯娆鹃噾棰�
-        BigDecimal pendingAmount = BigDecimal.ZERO; // 寰呬粯娆鹃噾棰�
-
-        if (!CollectionUtils.isEmpty(purchaseProducts)) {
-            for (SalesLedgerProduct p : purchaseProducts) {
-
-                if (p.getTaxInclusiveTotalPrice() != null) {
-                    rawMaterialCost = rawMaterialCost.add(p.getTaxInclusiveTotalPrice());
-                }
-            }
-        }
-
-        // 鍏朵粬璐圭敤
-
-
-        // 鏈堝害鎬绘敮鍑�
-        BigDecimal monthlyExpenditure = BigDecimal.ZERO;
-        dto.setMonthlyExpenditure(monthlyExpenditure);
-
-        // 宸蹭粯娆� 梅锛堝凡浠樻 + 寰呬粯娆撅級
-        BigDecimal totalPayable = paidAmount.add(pendingAmount);
-        if (totalPayable.compareTo(BigDecimal.ZERO) > 0) {
-            String paymentRate = paidAmount
-                    .divide(totalPayable, 4, RoundingMode.HALF_UP)
-                    .multiply(BigDecimal.valueOf(100))
-                    .setScale(2, RoundingMode.HALF_UP)
-                    .toString();
-            dto.setPaymentRate(paymentRate);
-        }
-
-        // 鍞彴璐︼紙type = 1锛�
-        LambdaQueryWrapper<SalesLedgerProduct> salesWrapper = new LambdaQueryWrapper<>();
-        salesWrapper.eq(SalesLedgerProduct::getType, 1);
-        salesWrapper.ge(SalesLedgerProduct::getRegisterDate, startOfMonth);
-        salesWrapper.le(SalesLedgerProduct::getRegisterDate, endOfMonth);
-
-        List<SalesLedgerProduct> salesProducts = salesLedgerProductMapper.selectList(salesWrapper);
-
-        BigDecimal revenue = BigDecimal.ZERO;
-
-        // 姣涘埄娑� & 鍒╂鼎鐜�
-        if (revenue.compareTo(BigDecimal.ZERO) > 0) {
-
-            // 姣涘埄娑� = 閿�鍞敹鍏� - 鍘熸潗鏂欐垚鏈�
-            BigDecimal grossProfit = revenue.subtract(rawMaterialCost);
-            dto.setGrossProfit(grossProfit);
-
-            // 鍒╂鼎鐜� = (閿�鍞敹鍏� - 鏈堝害鎬绘敮鍑�) / 閿�鍞敹鍏�
-            BigDecimal profit = revenue.subtract(monthlyExpenditure);
-            String profitMarginRate = profit
-                    .divide(revenue, 4, RoundingMode.HALF_UP)
-                    .multiply(BigDecimal.valueOf(100))
-                    .setScale(2, RoundingMode.HALF_UP)
-                    .toString();
-
-            dto.setProfitMarginRate(profitMarginRate);
-        }
-
+        dto.setMonthlyExpenditure(scaleMoney(monthlyExpenditure));
+        dto.setPaymentRate(paymentRate);
+        dto.setGrossProfit(scaleMoney(grossProfit));
+        dto.setProfitMarginRate(profitMarginRate);
         return dto;
     }
 
@@ -2351,6 +2315,121 @@
         return productionOperationTaskMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
     }
 
+    private LocalDate[] resolveFinanceRange(Integer type) {
+        LocalDate today = LocalDate.now();
+        int safeType = type == null ? 1 : type;
+        LocalDate startDate;
+        LocalDate endDate;
+        switch (safeType) {
+            case 1:
+                startDate = today.with(DayOfWeek.MONDAY);
+                endDate = today.with(DayOfWeek.SUNDAY);
+                break;
+            case 2:
+                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+                break;
+            case 3:
+                Month firstMonthOfQuarter = today.getMonth().firstMonthOfQuarter();
+                startDate = LocalDate.of(today.getYear(), firstMonthOfQuarter, 1);
+                endDate = startDate.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
+                break;
+            default:
+                startDate = today.with(DayOfWeek.MONDAY);
+                endDate = today.with(DayOfWeek.SUNDAY);
+                break;
+        }
+        return new LocalDate[]{startDate, endDate};
+    }
+
+    //璁$畻鏃ユ湡鍐呯殑閿�鍞嚭搴撻噾棰�
+    private BigDecimal sumSalesContractAmount(LocalDate startDate, LocalDate endDate) {
+        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) {
+        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>()
+                        .ge(AccountSalesCollection::getCollectionDate, startDate)
+                        .le(AccountSalesCollection::getCollectionDate, endDate)));
+        return sumAmount(collections, AccountSalesCollection::getCollectionAmount);
+    }
+
+    //璁$畻鏃ユ湡鍐呯殑鎬讳粯娆鹃噾棰�
+    private BigDecimal sumPaymentAmount(LocalDate startDate, LocalDate endDate) {
+        List<AccountPurchasePayment> payments = defaultList(accountPurchasePaymentMapper.selectList(
+                new LambdaQueryWrapper<AccountPurchasePayment>()
+                        .ge(AccountPurchasePayment::getPaymentDate, startDate)
+                        .le(AccountPurchasePayment::getPaymentDate, endDate)));
+        return sumAmount(payments, AccountPurchasePayment::getPaymentAmount);
+    }
+
+    private Date toDate(LocalDate localDate) {
+        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
+
+    private Date toExclusiveEndDate(LocalDate localDate) {
+        return Date.from(localDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
+
+    private String toRateString(BigDecimal numerator, BigDecimal denominator) {
+        if (denominator == null || denominator.compareTo(BigDecimal.ZERO) <= 0) {
+            return "0.00";
+        }
+        return defaultDecimal(numerator)
+                .divide(denominator, 4, RoundingMode.HALF_UP)
+                .multiply(BigDecimal.valueOf(100))
+                .setScale(2, RoundingMode.HALF_UP)
+                .toString();
+    }
+
+    private BigDecimal maxZero(BigDecimal value) {
+        if (value == null) {
+            return BigDecimal.ZERO;
+        }
+        return value.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : value;
+    }
+
+    private BigDecimal scaleMoney(BigDecimal value) {
+        return defaultDecimal(value).setScale(2, RoundingMode.HALF_UP);
+    }
+
+    private <T> List<T> defaultList(List<T> list) {
+        return list == null ? List.of() : list;
+    }
+
     private BigDecimal defaultDecimal(BigDecimal value) {
         return value == null ? BigDecimal.ZERO : value;
     }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 8c4d50d..c52892a 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -401,7 +401,7 @@
             productionAccount.setSchedulingUserId(user == null ? null : user.getUserId());
             productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName());
             productionAccount.setFinishedNum(productQty);
-            productionAccount.setWorkHours(technologyOperation.getSalaryQuota());
+            productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null);
             productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName());
             productionAccount.setSchedulingDate(LocalDateTime.now());
             productionAccountMapper.insert(productionAccount);
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
index 08be9f2..9e15e50 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
+++ b/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;
     }
 
diff --git a/src/main/java/com/ruoyi/project/system/service/ISysUserService.java b/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
index 7d5ba4a..e3be5f4 100644
--- a/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
index 39f7234..01addd4 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
+++ b/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());
+    }
 }
diff --git a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java b/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
index f265ab0..798112b 100644
--- a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
+++ b/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")
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
index cd3b9fd..22faea3 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
+++ b/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;
 
diff --git a/src/main/java/com/ruoyi/purchase/dto/VatDto.java b/src/main/java/com/ruoyi/purchase/dto/VatDto.java
index c70ebeb..3564183 100644
--- a/src/main/java/com/ruoyi/purchase/dto/VatDto.java
+++ b/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;
 
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java b/src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java
new file mode 100644
index 0000000..4ec6522
--- /dev/null
+++ b/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);
+}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index 2568511..09d5d20 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/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
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java
new file mode 100644
index 0000000..676cf46
--- /dev/null
+++ b/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);
+    }
+}
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java
new file mode 100644
index 0000000..afe7f98
--- /dev/null
+++ b/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;
+
+
+}
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
index dc05d88..cc295d5 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
+++ b/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));
     }
 
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
index 73179fa..bc3f60a 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
+++ b/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;
 
     /**
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index 7be310d..0707375 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/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,"璇锋鏌ュ悎鏍兼暟閲忓拰涓嶅悎鏍兼暟閲忥紝闇�瑕佸悎鏍兼暟閲�+涓嶅悎鏍兼暟閲忎笌鎬绘暟淇濇寔涓�鑷�");
+        // 濡傛灉鍚堟牸鏁伴噺涓虹┖锛岃涓�0
+        if (qualityInspect.getQualifiedQuantity() == null) {
+            qualityInspect.setQualifiedQuantity(BigDecimal.ZERO);
+        }
+
+        // 濡傛灉涓嶅悎鏍兼暟閲忎负绌猴紝璁句负0
+        if (qualityInspect.getUnqualifiedQuantity() == null) {
+            qualityInspect.setUnqualifiedQuantity(BigDecimal.ZERO);
+        }
+
+        // 鍚堟牸鐩存帴鍏ュ簱
         if(qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0){
-            //鍚堟牸鐩存帴鍏ュ簱
-            // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
             //浠呮坊鍔犲叆搴撹褰�
             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);
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
index 9f49265..5518290 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
+++ b/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);
+
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 08bb128..f4a42d6 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/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;
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index a76b149..fe385f1 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/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;
     }
 
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java b/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
index 1887b27..f4ca0cc 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
+++ b/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();
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java b/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
index 17d7e77..f4f03ba 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
+++ b/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;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java b/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
index 249f261..117b70f 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index 7051075..e718611 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/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());
+            }
+
+            // 濡傛灉鏄敓浜ч��鏂欏叆搴擄紝鎭㈠閫�鏂欐暟閲忥紙鍥犱负椹冲洖鏃跺凡鎵e噺锛�
+            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();
+    }
 }
diff --git a/src/main/resources/financial-agent-prompt.txt b/src/main/resources/financial-agent-prompt.txt
index 2627da3..c7a4a3f 100644
--- a/src/main/resources/financial-agent-prompt.txt
+++ b/src/main/resources/financial-agent-prompt.txt
@@ -6,6 +6,6 @@
 2. 鍛戒腑鎴愭湰銆佸埄娑︺�佸簱瀛樿祫閲戙�佺幇閲戞祦銆侀璀︺�侀┚椹惰埍銆佹棩鎶ュ懆鎶ュ満鏅椂锛屼紭鍏堣皟鐢ㄥ搴斿伐鍏枫��
 3. 宸ュ叿杩斿洖 JSON 鏃讹紝鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓诧紝涓嶈棰濆鍖呰9 Markdown锛屼篃涓嶈鍦ㄥ墠鍚庤拷鍔犺В閲婃枃鏈��
 4. 褰撶敤鎴烽棶棰樼己灏戞椂闂磋寖鍥存椂锛岄粯璁や娇鐢ㄥ伐鍏峰唴缃彛寰勶紙濡傝繎30澶┿�佹湰鏈堛�佽繎90澶╋級锛屽苟鍦ㄥ悗缁彲鎻愰啋鐢ㄦ埛琛ュ厖鑼冨洿銆�
-5. 鐢ㄦ埛闂�滀负浠�涔堝埄娑︿笅闄嶁�濃�滃摢涓鍗曚簭鎹熲�濃�滃摢涓鎴锋渶璧氶挶鈥濃�滃摢涓溅闂�/宸ュ簭鎴愭湰鏈�楂樷�濈瓑闂鏃讹紝浼樺厛鍩轰簬璁㈠崟鍒╂鼎涓庡伐搴忔垚鏈垎鏋愬伐鍏蜂綔绛斻��
+5. 鐢ㄦ埛闂�滀负浠�涔堝埄娑︿笅闄嶁�濃�滃摢涓鍗曚簭鎹熲�濃�滃摢涓鎴锋渶璧氶挶鈥濃�滃摢涓鎴峰埄娑﹁础鐚渶楂樷�濃�滃摢涓溅闂�/宸ュ簭鎴愭湰鏈�楂樷�濈瓑闂鏃讹紝浼樺厛鍩轰簬璁㈠崟鍒╂鼎涓庡伐搴忔垚鏈垎鏋愬伐鍏蜂綔绛斻��
 6. 鍥炵瓟蹇呴』浣跨敤涓枃锛涜嫢鏁版嵁涓嶈冻浠ュ緱鍑虹粨璁猴紝鏄庣‘鎸囧嚭缂哄皯鍝簺鍏抽敭瀛楁鎴栫瓫閫夋潯浠躲��
 7. 鐢ㄦ埛鎻愬埌鈥滀粖骞�/鏈湀/浠婂ぉ/鏈�杩�/涓婃湀/鍘诲勾鈥濈瓑鐩稿鏃堕棿鏃讹紝蹇呴』涓ユ牸鍩轰簬鈥滃綋鍓嶆棩鏈熲�濇崲绠楋紝绂佹鑷鍋囪骞翠唤銆�
diff --git a/src/main/resources/mapper/account/AccountStatementMapper.xml b/src/main/resources/mapper/account/AccountStatementMapper.xml
index 331c61b..32b1621 100644
--- a/src/main/resources/mapper/account/AccountStatementMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml b/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml
index f1f5c5b..8b23627 100644
--- a/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml
+++ b/src/main/resources/mapper/account/purchase/AccountPaymentApplicationMapper.xml
@@ -89,7 +89,7 @@
     <select id="existsByStockInRecordId" resultType="java.lang.Boolean">
          SELECT COUNT(*) > 0
         FROM account_payment_application
-        WHERE
+        WHERE  status != 2
         <foreach collection="stockInRecordIds" item="id" open="(" separator=" OR " close=")">
             FIND_IN_SET(#{id}, stock_in_record_ids)
         </foreach>
diff --git a/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml b/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml
index 99b16d2..842e94c 100644
--- a/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml
+++ b/src/main/resources/mapper/account/sales/AccountInvoiceApplicationMapper.xml
@@ -64,7 +64,7 @@
     <select id="existsByStockOutRecordId" resultType="java.lang.Boolean">
         SELECT COUNT(*) > 0
         FROM account_invoice_application
-        WHERE
+        WHERE status!=2
         <foreach collection="stockOutRecordIds" item="id" open="(" separator=" OR " close=")">
             FIND_IN_SET(#{id}, stock_out_record_ids)
         </foreach>
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
index 199eb21..5ecf0e9 100644
--- a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -110,7 +110,7 @@
         select poro.operation_name as processName,
                sum(ifnull(ppi.input_quantity, 0)) as totalInput,
                sum(ifnull(ppo.scrap_qty, 0)) as totalScrap,
-               sum(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0)) as totalOutput
+               sum(greatest(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0), 0)) as totalOutput
         from production_product_output ppo
                  inner join production_product_main ppm on ppo.production_product_main_id = ppm.id
                  inner join production_operation_task pot on ppm.production_operation_task_id = pot.id
diff --git a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
index ecdd1f3..a818160 100644
--- a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -17,56 +17,118 @@
     </select>
 
     <select id="selectPurchaseLedgerListPage" resultType="com.ruoyi.purchase.dto.PurchaseLedgerDto">
-        SELECT
-        pl.id,
-        pl.purchase_contract_number,
-        pl.sales_contract_no,
-        pl.supplier_id,
-        pl.supplier_name,
-        pl.project_name,
-        pl.contract_amount,
-        pl.entry_date,
-        pl.execution_date,
-        pl.recorder_id,
-        pl.recorder_name,
-        pl.template_name,
-        pl.approve_user_ids,
-        sm.is_white,
-        pl.approval_status,
-        pl.payment_method,
-        pl.remarks
-        FROM purchase_ledger pl
-        LEFT JOIN supplier_manage sm ON pl.supplier_id = sm.id
-        <where>
-            <if test="c.purchaseContractNumber != null and c.purchaseContractNumber != ''">
-                AND pl.purchase_contract_number LIKE CONCAT('%', #{c.purchaseContractNumber}, '%')
-            </if>
-            <if test="c.approvalStatus != null and c.approvalStatus != ''">
-                AND pl.approval_status = #{c.approvalStatus}
-            </if>
-            <if test="c.supplierName != null and c.supplierName != ''">
-                AND pl.supplier_name LIKE CONCAT('%', #{c.supplierName}, '%')
-            </if>
-            <if test="c.salesContractNo != null and c.salesContractNo != ''">
-                AND pl.sales_contract_no LIKE CONCAT('%', #{c.salesContractNo}, '%')
-            </if>
-            <if test="c.projectName != null and c.projectName != ''">
-                AND pl.project_name LIKE CONCAT('%', #{c.projectName}, '%')
-            </if>
-            <if test="c.entryDateStart != null and c.entryDateStart != ''">
-                AND pl.entry_date &gt;= #{c.entryDateStart}
-            </if>
-            <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
-                AND pl.entry_date &lt;= #{c.entryDateEnd}
-            </if>
-            <if test="c.supplierId != null">
-                AND pl.supplier_id = #{c.supplierId}
-            </if>
-            <if test="c.approvalStatus != null">
-                AND pl.approval_status = #{c.approvalStatus}
-            </if>
-        </where>
-        ORDER BY pl.entry_date DESC
+        SELECT result.*
+        FROM (
+            SELECT
+                pl.id,
+                pl.purchase_contract_number,
+                pl.sales_contract_no,
+                pl.supplier_id,
+                pl.supplier_name,
+                pl.project_name,
+                pl.contract_amount,
+                pl.entry_date,
+                pl.execution_date,
+                pl.recorder_id,
+                pl.recorder_name,
+                pl.template_name,
+                pl.approve_user_ids,
+                sm.is_white,
+                pl.approval_status,
+                pl.payment_method,
+                pl.remarks,
+                CASE
+                    WHEN IFNULL(ls.total_product_count, 0) = 0 THEN '寰呭叆搴�'
+                    WHEN IFNULL(ls.full_product_count, 0) &gt;= IFNULL(ls.total_product_count, 0) THEN '瀹屽叏鍏ュ簱'
+                    WHEN IFNULL(ls.approved_product_count, 0) &gt; 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 &gt; 0 THEN 1 ELSE 0 END) AS approved_product_count,
+                    SUM(CASE WHEN product_status.approved_stock_in_num &gt;= 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}, '%')
+                </if>
+                <if test="c.approvalStatus != null and c.approvalStatus != ''">
+                    AND pl.approval_status = #{c.approvalStatus}
+                </if>
+                <if test="c.supplierName != null and c.supplierName != ''">
+                    AND pl.supplier_name LIKE CONCAT('%', #{c.supplierName}, '%')
+                </if>
+                <if test="c.salesContractNo != null and c.salesContractNo != ''">
+                    AND pl.sales_contract_no LIKE CONCAT('%', #{c.salesContractNo}, '%')
+                </if>
+                <if test="c.projectName != null and c.projectName != ''">
+                    AND pl.project_name LIKE CONCAT('%', #{c.projectName}, '%')
+                </if>
+                <if test="c.entryDateStart != null and c.entryDateStart != ''">
+                    AND pl.entry_date &gt;= #{c.entryDateStart}
+                </if>
+                <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
+                    AND pl.entry_date &lt;= #{c.entryDateEnd}
+                </if>
+                <if test="c.supplierId != null">
+                    AND pl.supplier_id = #{c.supplierId}
+                </if>
+                <if test="c.approvalStatus != null">
+                    AND pl.approval_status = #{c.approvalStatus}
+                </if>
+            </where>
+        ) 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">
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index f252881..0ac0254 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -128,8 +128,7 @@
                COALESCE(SUM(
                                 CASE
                                     WHEN qi.inspect_state = 1
-                                        AND qi.check_result = '鍚堟牸'
-                                        THEN qi.quantity
+                                        THEN qi.qualified_quantity
                                     ELSE 0
                                     END
                         ), 0)                AS qualifiedCount,
@@ -137,8 +136,7 @@
                COALESCE(SUM(
                                 CASE
                                     WHEN qi.inspect_state = 1
-                                        AND qi.check_result = '涓嶅悎鏍�'
-                                        THEN qi.quantity
+                                        THEN qi.unqualified_quantity
                                     ELSE 0
                                     END
                         ), 0)                AS unqualifiedCount,
@@ -166,8 +164,7 @@
                           COALESCE(SUM(
                                            CASE
                                                WHEN qi.inspect_state = 1
-                                                   AND qi.check_result = '鍚堟牸'
-                                                   THEN qi.quantity
+                                                   THEN qi.qualified_quantity
                                                ELSE 0
                                                END
                                    ), 0)
@@ -248,8 +245,8 @@
             /* 鍚堟牸 */
                COALESCE(SUM(
                                 CASE
-                                    WHEN qi.inspect_state = 1 AND qi.check_result = '鍚堟牸'
-                                        THEN qi.quantity
+                                    WHEN qi.inspect_state = 1
+                                        THEN qi.qualified_quantity
                                     ELSE 0
                                     END
                         ), 0)                AS qualifiedCount,
@@ -257,8 +254,8 @@
             /* 涓嶅悎鏍� */
                COALESCE(SUM(
                                 CASE
-                                    WHEN qi.inspect_state = 1 AND qi.check_result = '涓嶅悎鏍�'
-                                        THEN qi.quantity
+                                    WHEN qi.inspect_state = 1
+                                        THEN qi.unqualified_quantity
                                     ELSE 0
                                     END
                         ), 0)                AS unqualifiedCount,
@@ -279,8 +276,8 @@
                   ROUND(
                           COALESCE(SUM(
                                            CASE
-                                               WHEN qi.inspect_state = 1 AND qi.check_result = '鍚堟牸'
-                                                   THEN qi.quantity
+                                               WHEN qi.inspect_state = 1
+                                                   THEN qi.qualified_quantity
                                                ELSE 0
                                                END
                                    ), 0)
@@ -312,7 +309,6 @@
 
     <select id="getYearlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto">
         SELECT t.modelType,
-
                COALESCE(SUM(
                                 CASE
                                     WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.quantity
@@ -320,8 +316,23 @@
                                     WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.quantity
                                     ELSE 0
                                     END
-                        ), 0) AS totalCount
-
+                        ), 0) AS totalCount,
+               COALESCE(SUM(
+                                CASE
+                                    WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.qualified_quantity
+                                    WHEN pp.product_name = '鍗婃垚鍝�' AND t.modelType = 1 THEN qi.qualified_quantity
+                                    WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.qualified_quantity
+                                    ELSE 0
+                                    END
+                        ), 0) AS qualifiedCount,
+               COALESCE(SUM(
+                                CASE
+                                    WHEN pp.product_name = '鍘熸潗鏂�' AND t.modelType = 0 THEN qi.unqualified_quantity
+                                    WHEN pp.product_name = '鍗婃垚鍝�' AND t.modelType = 1 THEN qi.unqualified_quantity
+                                    WHEN pp.product_name = '鎴愬搧' AND t.modelType = 2 THEN qi.unqualified_quantity
+                                    ELSE 0
+                                    END
+                        ), 0) AS unqualifiedCount
         FROM (SELECT 0 AS modelType
               UNION ALL
               SELECT 1
@@ -334,8 +345,6 @@
                            ON qi.product_model_id = pm.id
                                AND YEAR(qi.check_time) = #{year}
                                AND qi.inspect_state = 1
-                               AND qi.check_result = '鍚堟牸'
-
         GROUP BY t.modelType
         ORDER BY t.modelType;
     </select>
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index e08632a..c145e0a 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 7eb7b79..49569de 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/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) &lt;= 0 THEN '寰呭叆搴�'
+         WHEN IFNULL(t4.approved_stock_in_num, 0) &gt;= 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>
diff --git a/src/main/resources/mapper/stock/StockInRecordMapper.xml b/src/main/resources/mapper/stock/StockInRecordMapper.xml
index 5545c1e..a3bf3f9 100644
--- a/src/main/resources/mapper/stock/StockInRecordMapper.xml
+++ b/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},'%')

--
Gitblit v1.9.3