| doc/20260521_首页HomeController接口升级前端变更文档.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| doc/20260922_backfill_sales_ledger_approval_rollback.sql | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| doc/20260922_delete_RB120260814001_rollback.sql | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| doc/20260922_库存详情拆分库存入库出库三接口前端联调文档.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| doc/20260922_油品出入库图片URL失效修复说明.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/sales/SalesLedgerProductMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/stock/StockInRecordMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/stock/StockInventoryMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/stock/StockOutRecordMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
doc/20260521_Ê×Ò³HomeController½Ó¿ÚÉý¼¶Ç°¶Ë±ä¸üÎĵµ.md
@@ -111,3 +111,41 @@ 2. éè¦ææ¥æå¤ççæ¿æ¶ï¼ä½¿ç¨ `bizDate` / `planDate`ã 3. è页é¢å¯ä¸æ¹ï¼ç»§ç»æ²¿ç¨ååæ°ä¹è½æ£å¸¸èè°ã ## 5. éè´ååå¸å£å¾ä¿®æ£ï¼2026-09-22ï¼ `GET /home/rawMaterialPurchaseAmountRatio` ä¹åæäº§åæ ãåææãåç±»è¿æ»¤éè´æç»ï¼å®é éè´å°è´¦ç»è®°çåç±»ï¼æ´æ²¹ãçç«å¨ï¼æå¨ãæå/æåæ²¹ãã设å¤è®¾æ½/å ¬å ±å®å ¨è®¾å¤ãä¸ï¼å¯¼è´æ¥å£**æè¿å空æ°ç»**ã大屿 æ°æ®ã ç°å·²æ¹ä¸º**ä¸ãå产åéå®éé¢åæãåå£å¾**ï¼åå ¨é¨éè´æç»ï¼`type=2`ï¼ææç»ä¸çåç±» `product_category` èåï¼éé¢å `tax_inclusive_total_price`ï¼Top5 ååºã | 项 | åå | | --- | --- | | è¯·æ± | ä¸åï¼æ åæ°ï¼ | | ååºç»æ | ä¸åï¼`name` / `value` / `rate`ï¼ | | `name` è¯ä¹ | **ç±ãåææåç±»åãå为ãéè´æç»ç»è®°çåç±»ã** | | è¿æ»¤ | ä» æé¤å类为空çè¡ | 注æäºé¡¹ï¼ 1. ååºç»ææ²¡åï¼å端**ä¸éè¦æ¹ä»£ç **ï¼ä½è¥å¾è¡¨æ é¢åæ»äºãåææéè´éé¢å æ¯ãï¼å»ºè®®æ¹æãéè´ååå¸ãä¹ç±»ç䏿§å«æ³ââç°å¨è¿åçæ¯å ¨é¨éè´åç±»ï¼ä¸åªæ¯åææã 2. ä¿®æ¹çæ¯ Mapper XMLï¼**éè¦éå¯å端**æçæï¼`devtools.restart.enabled: false`ï¼ã 3. åæºç `selectRawMaterialExpense`ï¼è´¹ç¨ææéçãåææãéé¢ï¼åæ ·æäº§åæ ãåææãåæ è¿æ»¤ï¼ç®å**æªæ¹**ï¼å¨è¯¥ç§æ·æ°æ®ä¸åæ ·ä¼ç®æ 0ãæ¬å¾è¡¨çåç±»å£å¾è°æ´ä¸æ¶åå®ï¼æ¯å¦ä¸å¹¶æ¾å¼å¦è¡ç¡®è®¤ã ## 6. åºå ¥åºè¶å¿äº§ååç±»è¿æ»¤ä¿®æ£ï¼2026-09-22ï¼ `GET /home/productInOutAnalysis?type=<1|2|3>` ä¹ååªæ¯å¯¹äº§ååç±»ç**ç´æ¥åèç¹**ï¼`p.parent_id = rootCategoryId`ï¼ï¼èäº§åæ æ¯ã大类 â åç±» â å ·ä½äº§åãä¸å±ã产ååå·ï¼`product_model`ï¼æå¨**å¶å产å**ä¸ï¼æä»¥åå·æ°¸è¿å½ä¸ä¸å°è¯¥æ¡ä»¶ â 7 天è¶å¿æä¸ºå ¨ 0ã ç°å·²æ¹ä¸º**éå½åæ´æ£µåç±»åæ **ï¼`WITH RECURSIVE product_tree`ï¼ï¼ä¸é¡¹ç®éå ¶ä»åºå/äº§åæ¥è¯¢ï¼`StockInRecordMapper`ã`StockOutRecordMapper`ã`StockInventoryMapper`ã`ProductModelMapper`ï¼ä¿æåä¸åæ³ãéå½ CTE å卿¬å·å ï¼è¯å¥ä»ä»¥ `SELECT` å¼å¤´ï¼æ°æ®æéæ¦æªå¨å¯¹ `stock_in_record` / `stock_out_record` çè¿æ»¤ç §å¸¸çæã | 项 | åå | | --- | --- | | è¯·æ± | ä¸åï¼`type`ï¼1 åææ / 2 æå / 3 åæåï¼ | | ååºç»æ | ä¸åï¼`date` / `inCount` / `outCount`ï¼è¿ 7 å¤©ææ¥ï¼ | | `type=1`ï¼åææï¼ | è¯¥ç§æ·**ä»ä¸ºç©º**ï¼äº§ååå·æ²¡ææå¨ãåææãåæ ä¸çï¼å±æ°æ®ç°ç¶èéç¼ºé· | | `type=2`ï¼æåï¼ | ä¿®æ£ååºç°æ°æ®ï¼æ´æ²¹å¨ãæå/æåæ²¹/æ´æ²¹ãä¸ï¼ | 注æäºé¡¹ï¼ 1. ååºç»ææ²¡åï¼å端**ä¸éè¦æ¹ä»£ç **ï¼ä¿®æ¹çæ¯ Mapper XMLï¼**éè¦éå¯å端**æçæã 2. åç±»æ å°æç²åºï¼ãåå ¬ç¨åãã设å¤è®¾æ½ããå±åºå¤ç½®æ¬¡çå±åºãè¿ä¸å¤§ç±»ä¸å¨ `type` ç 1/2/3 æ å°å ï¼æå¨å®ä»¬ä¸é¢çåå·ï¼å¦çç«å¨ï¼ä»»ä½ `type` 齿¥ä¸å°ãè¥å¤§å±éè¦è¦çï¼éæ©å± `type` åå¼ææ¹æ `product_category` è¿æ»¤ï¼å¦è¡ç¡®è®¤ã 3. åºåºä¾§æªæå®¡æ¹ç¶æè¿æ»¤ï¼å¾ 审æ¹ï¼`approval_status IN (0,3)`ï¼çåºåºåä¹ä¼è®¡å ¥è¶å¿ï¼å¦éåªç已审æ¹éè¿çéï¼å¦è¡ç¡®è®¤ã doc/20260922_backfill_sales_ledger_approval_rollback.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ -- åæ»èæ¬ï¼éå®å°è´¦ RB120260810001(id=94) / RB120260611001(id=97) è¡¥å½ç审æ¹è®°å½ -- çææ¶é´ï¼2026-09-22 æ¥æºåºï¼36.213.90.123:11101 / product-inventory-management-rbhb -- è¡¥å½å 容ï¼å½æ¶è¿ä¸¤æ¡å°è´¦ç± Excel å¯¼å ¥äº§çï¼approval_status ä¸ºç©ºãæ å®¡æ¹å®ä¾ã -- æå®ä¾ 265ï¼å°è´¦ 103ï¼å·²éè¿ï¼çå½¢ç¶è¡¥äº 2 å®ä¾ x (1 node + 1 task + 2 record)ï¼ -- å¹¶æ sales_ledger.approval_status 置为 'éè¿'ã -- æ§è¡é¡ºåºï¼record -> task -> node -> instance -> sales_ledgerï¼å¤é®è¯ä¹ç±åºç¨ç»´æ¤ï¼è¿éæä¾èµååºå ï¼ -- 注æï¼ä¸¤ä¸ªå®ä¾ id åå«ä¸º 268/269ï¼æ¢åºæ§è¡æ¶ä»¥ instance_no 为å delete from approval_record where instance_id in (select id from ( select id from approval_instance where instance_no in ('SP20260922001','SP20260922002')) t); delete from approval_task where instance_id in (select id from ( select id from approval_instance where instance_no in ('SP20260922001','SP20260922002')) t); delete from approval_instance_node where instance_id in (select id from ( select id from approval_instance where instance_no in ('SP20260922001','SP20260922002')) t); delete from approval_instance where instance_no in ('SP20260922001','SP20260922002'); -- ä» è¿åæ¬æ¬¡è¡¥å½ç两æ¡ï¼è¥æé´å·²è¢«äººå·¥éæ°èµ°æµç¨/驳åï¼ä¸è¦æ§è¡ä¸é¢è¿å¥ update sales_ledger set approval_status = null where id in (94, 97); doc/20260922_delete_RB120260814001_rollback.sql
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ -- åæ»èæ¬ï¼éå®å°è´¦ RB120260814001ï¼æ±¡æ³¥å¤ç½®æå¡ï¼å é¤åçåæ ·æ°æ® -- çææ¶é´ï¼2026-09-22 09:33:22 æ¥æºåºï¼36.213.90.123:11101 / product-inventory-management-rbhb -- æ¢å¤é¡ºåºï¼å sales_ledgerï¼å sales_ledger_productï¼æå production_plan -- 1. sales_ledger (id=95) INSERT INTO `sales_ledger` VALUES (95,'RB120260814001',NULL,'污泥å¤ç½®æå¡','2026-08-14','ææè³',445,'å æçä¾å¸é宿°¸æ³°ç¯ä¿ç§ææéå ¬å¸','åæ²¹',NULL,NULL,NULL,NULL,NULL,NULL,'320',NULL,NULL,100,75471.00,'2025-05-16 00:00:00','é¶è¡è½¬è´¦','2026-08-14 16:00:00',320,100,75471.00); -- 2. sales_ledger_product (id=199) INSERT INTO `sales_ledger_product` VALUES (199,95,'污泥','æ®å®','å¨',1.00,NULL,6,75471.00,75471.00,71199.06,'å¢ä¸ç¥¨',1,NULL,429,'ååªå°','2026-09-18 15:47:56',NULL,0,1,320,100,1,NULL); -- 3. production_plan (id=144) INSERT INTO `production_plan` VALUES (144,95,199,'JH202608140001','2026-08-15 00:00:00.000000',NULL,'2026-09-17 17:54:25.654946','2026-09-17 17:54:25.655131',320,320,100,429,1.000000,0,'éå®','2026-08-15 00:00:00.000000',NULL); doc/20260922_¿â´æÏêÇé²ð·Ö¿â´æÈë¿â³ö¿âÈý½Ó¿Úǰ¶ËÁªµ÷Îĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,185 @@ # åºåè¯¦æ æå为ãåºå / å ¥åºè®°å½ / åºåºè®°å½ã䏿¥å£ å端èè°ææ¡£ æ´æ°æ¶é´ï¼2026-09-22 éç¨çæ¬ï¼æ¬æ¬¡åç«¯åæ´å --- ## 1. é®é¢ï¼ä¸ä¸ªæ¥å£å½ä¸ä¸ªç¨ åºå详æ å¼¹çªéåæ¶å±ç¤º**åºå**ã**å ¥åºè®°å½**ã**åºåºè®°å½**ä¸åå 容ï¼ä½ä¸åé½åèªåä¸ä¸ªæ¥å£ï¼ ``` GET /stockInventory/pageListCombinedStockInventory?topParentProductId=276¤t=1&size=100 ``` èè¿ä¸ªæ¥å£ç设计å£å¾æ¯ï¼ - **æè§æ ¼èå**ââä¸è¡ä¸ä¸ª `product_model_id`ï¼`batch_no` ç¨ `GROUP_CONCAT` æ¼æä¸ä¸²ï¼ - **å ¥åºä¿¡æ¯**ââåè¯¥è§æ ¼**æè¿ä¸æ¡** `stock_in_record` çåæ®µï¼å¨ç½å·/å¯åº¦/è¿ç£ çï¼ï¼ä¸**ä¸å¸¦æ¹å·æ¡ä»¶**ï¼ - **åºåºä¿¡æ¯**ââåè¯¥è§æ ¼**æè¿ä¸æ¡** `stock_out_record` çåæ®µï¼**ä¸å¸¦æ¹å·ãä¸å¸¦åæ ¼ç±»åãä¹ä¸çå®¡æ ¸ç¶æ**ã 以 `topParentProductId=276`ï¼æåï¼ä¸ºä¾ï¼æ¥å£å®é åªè¿å **1 è¡**ï¼ | åæ®µ | è¿åå¼ | | --- | --- | | model / productName | `0#æ´æ²¹` / `æ´æ²¹` | | batchNo | `20260921-CY001-001,20260921-CY001-002`ï¼ä¸¤ä¸ªæ¹æ¬¡æ¼å¨ä¸èµ·ï¼ | | qualifiedQuantity | `65.3400`ï¼ä¸¤æ¹åè®¡ï¼ | | tankNo | `01#` | | netWeight | `32.8000`ï¼**åªæ¯ææ°é£æ¹**çåéï¼ä¸æ¯åè®¡ï¼ | | outTonnage | `7.9800` | | outCustomerName | `æ°çææ©çç¯å¢ç§ææéå ¬å¸` | é®é¢å°±å¨è¿ï¼**å ¥åº/åºåºè¦çæ¯"è®°å½å表"ï¼æ¥å£ç»çå´æ¯"èåè¡ä¸çä¸ä¸ªå¿«ç §å¼"**ãæä»¥åä¸è¡çåºåæ¯ 65.34ï¼å ¥åºåéå´æ¯ 32.80ï¼å¯¹ä¸ä¸ï¼åºåºæ´åªæä¸æ¡ï¼åå²è®°å½å ¨çä¸å°ã --- ## 2. æ¹æ³ï¼ç»è®ºï¼ ä¸ä¸ªåºæ¯åç¨åçæ¥å£ï¼ | åºæ¯ | æ¥å£ | æ¬æ¬¡æ¯å¦æ¹å¨ | | --- | --- | --- | | åºå | `GET /stockInventory/pageListCombinedStockInventory` | ä¸å | | å ¥åºè®°å½ | `GET /stockInRecord/listPage` | **æ°å¢ `productModelId` è¿æ»¤** | | åºåºè®°å½ | `GET /stockOutRecord/listPage` | **æ°å¢ `productModelId` è¿æ»¤** | ``` åºå详æ GET /stockInventory/pageListCombinedStockInventory?topParentProductId=276 å ¥åºè®°å½ GET /stockInRecord/listPage?topParentProductId=276&productModelId=407 åºåºè®°å½ GET /stockOutRecord/listPage?topParentProductId=276&productModelId=407 ``` è¿ä¸¤ä¸ªè®°å½æ¥å£æ¬æ¥å°±åå¨ï¼å ¥åºç®¡çèå 2355 / åºåºç®¡çèåç¨å®ä¿©ï¼ï¼**ä¸ç´æ¯è¿åå ¨é¨è®°å½çå页å表**ï¼åªæ¯åå 缺ä¸ä¸ª"ç²¾ç¡®å°æä¸ªè§æ ¼"çåæ°ï¼åªè½é `model` 模ç³å¹é ãæ¬æ¬¡æ `productModelId` è¡¥ä¸ã ### 2.1 交äºå£å¾ï¼ä¸ä¸ª tab åèªå页æ¥è¯¢ åºå详æ éçãåºå / å ¥åºè®°å½ / åºåºè®°å½ãæ¯**ä¸ä¸ª tabï¼åºåï¼ï¼ç¹åªä¸ªæ¥åªä¸ª**ï¼ä¸æ¯æå¼å¼¹çªä¸æ¬¡æ§æä¸ç±»æ°æ®å ¨æåæ¥ãä¸ä¸ª tab åèªç¬ç«ä¼ å页忰ãåèªç»´æ¤ `current` / `size`ï¼åæ¢ tab æ¶æé请æ±ï¼ | tab | è¯·æ± | å页 | | --- | --- | --- | | åºå | `pageListCombinedStockInventory` | 该æ¥å£æè§æ ¼èåï¼ä¸ä¸ªå¼¹çªéå¸¸åªæå è¡ï¼`size=100` è¶³å¤ | | å ¥åºè®°å½ | `stockInRecord/listPage` | **èµ°æ£å¸¸å页**ï¼`size` æ tab å è¡¨æ ¼çæ¯é¡µæ¡æ°ä¼ ï¼å¦ 10 / 20ï¼ | | åºåºè®°å½ | `stockOutRecord/listPage` | **èµ°æ£å¸¸å页**ï¼åä¸ | **ä¸è¦ä¸ºäº"è¦å ¨é¨æ°æ®"èä¼ è¶ å¤§ `size` 䏿¬¡æå®**ï¼`total` å·²ç»å¨è¿åä½éï¼`data.total`ï¼ï¼å端æ¿å®æ¸²ææ»æ¡æ°ãæ£å¸¸ç¿»é¡µå³å¯ï¼ä¼ è¶ å¤§ `size` 䏿¦è¶ è¿è®°å½æ»æ°ï¼è¶ åºé¨ååç«¯ä¹æ¿ä¸å°ï¼æ¯å页ä¸éï¼ä¸æ¯å ¨éè¯ä¹ï¼ï¼è®°å½å¤äºè¿ä¼ææ ¢æ¥å£ã --- ## 3. æ¬æ¬¡å端æ¹å¨ åªæ¹äºä¸¤æ¡æ¥è¯¢ï¼åå ä¸ä¸ªå¯éè¿æ»¤æ¡ä»¶ï¼ä¸ä¼ æ¶è¡ä¸ºä¸å页é¢å®å ¨ä¸è´ï¼ï¼ | æä»¶ | æ¹å¨ | | --- | --- | | `src/main/resources/mapper/stock/StockInRecordMapper.xml` | `listPage` æ°å¢ `params.productModelId` â `and sir.product_model_id = #{params.productModelId}` | | `src/main/resources/mapper/stock/StockOutRecordMapper.xml` | `listPage` æ°å¢ `params.productModelId` â `and sor.product_model_id = #{params.productModelId}` | Controller / Service / DTO åæ éæ¹å¨ââ`StockInRecordDto`ã`StockOutRecordDto` 已继æ¿å« `productModelId` ç POJOï¼Spring ç´æ¥ä» query string ç»å®ã --- ## 4. 请æ±åæ° ### 4.1 å ¥åºè®°å½ `GET /stockInRecord/listPage` | åæ° | ç±»å | å¿ å¡« | 说æ | | --- | --- | --- | --- | | `topParentProductId` | Long | å¦ | äº§åæ æ ¹èç¹ idï¼æ¥è¯¥èç¹**åå ¶ææåå**产åä¸çè®°å½ | | `productModelId` | Long | å¦ | **æ¬æ¬¡æ°å¢**ãç²¾ç¡®å°æä¸ªè§æ ¼ï¼ä¸è¡ = ä¸ä¸ªè§æ ¼ï¼ | | `batchNo` | String | å¦ | æ¹å·ï¼**模ç³**å¹é | | `productName` | String | å¦ | 产ååç§°ï¼æ¨¡ç³ | | `model` | String | å¦ | è§æ ¼ï¼æ¨¡ç³ | | `type` | String | å¦ | `'0'` åæ ¼ / `'1'` ä¸åæ ¼ | | `recordType` | String | å¦ | å ¥åºæ¥æºç±»åï¼éè´å ¥åº / çäº§å ¥åº çï¼ | | `timeStr` | String | å¦ | æ `create_time` 模ç³å¹é ï¼å¦ `2026-09-21`ï¼ | | `current` / `size` | int | å¦ | å页ï¼é»è®¤ `current=1`ã`size=10` | ### 4.2 åºåºè®°å½ `GET /stockOutRecord/listPage` åæ°åä¸ï¼`timeStr`ã`productName`ã`model`ã`batchNo`ã`productModelId`ã`type`ã`recordType`ã`topParentProductId`ï¼ï¼æ¤å¤è¿åä½è¿å¸¦éå®ååå· `salesContractNo`ã > `topParentProductId` ä¸ `productModelId` **å¯åæ¶ä¼ **ï¼æ¯ `AND` å ³ç³»ãæ¢ç¶ `productModelId` å·²ç»è½å¯ä¸å®ä½è§æ ¼ï¼åªä¼ å®ä¸ä¸ªå°±å¤ï¼åæ¶ä¼ ç¸å½äºå¤ä¸å±"å¿ é¡»å¨è¿æ£µäº§åæ ä¸"çä¿é©ã --- ## 5. è¿åå½¢æ 两个æ¥å£é½è¿å `AjaxResult`ï¼åé¡µæ°æ®å¨ `data` éï¼ä¸åºåæ¥å£ç `R` ç»æä¸è´ï¼é½æ¯ `code` / `msg` / `data`ï¼ï¼ ``` data.records[] // è®°å½æ°ç» data.total // æ»æ¡æ° data.current / data.size / data.pages ``` `records` éçåæ®µæ¯ `sir.*`ï¼æ `sor.*`ï¼**æ´å¼ 表çå**ï¼åå ï¼ | æ¥å£ | é¢å¤å段 | | --- | --- | | å ¥åº | `productName`ã`model`ã`unit`ã`createBy`ï¼å»ºå人æµç§°ï¼ã`salesContractNo`ï¼ä»£å¨å ¥åºç»å®çéå®ååå·ï¼ã`sourceOrderNo`ï¼æºåå·ï¼ | | åºåº | `productName`ã`model`ã`unit`ã`createBy`ã`salesContractNo`ï¼å¯ç»å¤ä¸ªå°è´¦ï¼éå·æ¼æ¥ï¼ | å ¥åºä¾§å±ç¤ºå段ï¼å¨ç½/æ²¹åº/ç©æµ/è¿ç£ ï¼ä¸åºåºä¾§å段ï¼`outCategory`ã`outTonnage`ã`outDate`ã客æ·ã车è¾ãè¿ç£ ãç §çï¼é½æ¯åæ ·å¸¦åºçï¼**ä¸åºåºè®°å½å表ãå ¥åºç®¡çå表è¿åçæ¯åä¸å¥å段**ï¼å端ç»ä»¶å¯ç´æ¥å¤ç¨ã --- ## 6. 宿µç¤ºä¾ï¼åºå ç宿°æ®ï¼ ### 6.1 å ¥åºè®°å½ ``` GET /stockInRecord/listPage?topParentProductId=276&productModelId=407¤t=1&size=100 ``` è¿å **2 æ¡**ï¼åæ¥è忥å£åªç»ä¸ä¸ª 32.80ï¼ï¼ | id | batchNo | stockInNum | type | approvalStatus | tankNo | netWeight | | --- | --- | --- | --- | --- | --- | --- | | 236 | `20260921-CY001-002` | 32.8000 | 0 | 1 | `01#` | 32.80 | | 235 | `20260921-CY001-001` | 32.5400 | 0 | 1 | `01#` | 32.54 | ä¸¤æ¡ `stockInNum` ç¸å = 65.34ï¼ä¸åºåè¡ç `qualifiedQuantity` 对å¾ä¸äºã ### 6.2 åºåºè®°å½ ``` GET /stockOutRecord/listPage?topParentProductId=276&productModelId=407¤t=1&size=100 ``` è¿å **1 æ¡**ï¼`id=257`ï¼`outTonnage=7.98`ï¼`outCategory=代å¨`ï¼`customerName=æ°çææ©çç¯å¢ç§ææéå ¬å¸`ï¼`tankNo=01#`ï¼`approvalStatus=1`ï¼æ³¨æè¿æ¡ç `batchNo` å `type` 齿¯ **NULL**ï¼æ²¹ååºåºè®°å½ä¸è½æ¹å·/ç±»åï¼ã --- ## 7. 注æäºé¡¹ï¼èè°åå¿ çï¼ 1. **`pageListCombinedStockInventory` ç `out*` ä¸å ¥åºå段ä¿çä¸å¨**ãåºå管çå表ï¼èå 2352ï¼å¨ç¨ `tankNo`ã`oilProduct`ã`density`ãè¿ç£ çåï¼æä»¥æ¬æ¬¡**没æå é¤**è¿äºåæ®µï¼æ¥å£è¿åç»æå®å ¨æ²¡åââåªæ¯å端**ä¸è¦åæ¿å®å½å ¥åº/åºåºæç»ç¨**ã 2. **该æ¥å£ç `batch_no` æ¯æ¼æ¥ä¸²**ã夿¹æ¬¡è§æ ¼ä¼è¿å `"20260921-CY001-001,20260921-CY001-002"`ï¼ä¸è½å½å个æ¹å·å±ç¤ºæåä¼ ãè¦ææ¹æ¬¡çï¼èµ°å ¥åºè®°å½æ¥å£ï¼ä¸è¡ä¸ä¸ª `batch_no`ï¼ãè¿ä¹æ¯æ¬æ¬¡æåçæ ¸å¿åå ã 3. **å ¥åº/åºåºå表ä¸è¿æ»¤å®¡æ ¸ç¶æ**ï¼å¾ å®¡æ ¸ï¼0ï¼ãå®¡æ ¸æªéè¿ï¼2ï¼çè®°å½é½ä¼è¿åãåºå详æ è¥è¦åªå±ç¤º"å·²çæ"çè®°å½ï¼å端æ `approvalStatus === 1` èªè¡è¿æ»¤å±ç¤ºã**å表æ¥å£ç®å䏿¯ææ `approvalStatus` ä¼ åè¿æ»¤**ï¼ä¼ äºä¼è¢«å¿½ç¥ï¼ââéè¦åç«¯æ¯æçè¯å说ã 4. **`type` å¯è½ä¸º NULL**ãæ²¹ååºåºçè®°å½ `type` æ¯ç©ºä¸²/NULLï¼å端ä¸è¦å `type === '0'` 硬å¤åæ ¼ï¼å¦åè¿ç±»è®°å½ä¼è¢«æ¼æãåªæå½ `type` æå¼æ¶æåºåï¼`'0'` åæ ¼ã`'1'` ä¸åæ ¼ã 5. **å®¡æ ¸ç¶æåå¼**ï¼`ReviewStatusEnum`ï¼ï¼`0` å¾ å®¡æ ¸ã`1` å·²å®¡æ ¸ã`2` å®¡æ ¸æªéè¿ã注æè¿è·è´¢å¡æ¨¡åç `ApprovalStatusEnum`ï¼0 è稿 / 1 å¾ å®¡æ¹ / 2 审æ¹ä¸ / 3 å·²éè¿ / 4 已驳åï¼**䏿¯åä¸å¥**ï¼å«æ··ç¨ã 6. **è¿ä¸¤ä¸ªå表æ¥è¯¢ä¸åæ°æ®æéè¿æ»¤**ãå®ä»¬ç SQL 以 `WITH RECURSIVE` å¼å¤´ï¼èæ°æ®æéæ¦æªå¨åªå¤ç以 `select` å¼å¤´ç SQLï¼æä»¥ä¸ä¼è¿½å `create_user` / `dept_id` æ¡ä»¶ââä¸åºåå表æ¥å£è¡ä¸ºä¸è´ï¼æ¢è´¦å·ä¸ä¼çä¸å°è®°å½ã 7. **å¨ç½å·ä»¥å ¥åºè®°å½ä¸ºå**ãåºåèåè¡ä¸çå¨ç½å·æ¯"è¯¥è§æ ¼æè¿ä¸æ¬¡å ¥åº"çå¼ï¼åä¸è§æ ¼å¤ç½æ¶åªæ¾ç¤ºä¸ä¸ªï¼å ¥åºè®°å½æ¥å£ä¸çæ¯**æ¹æ¬¡çº§**çåç¡®å¼ã 8. **å ¥åº/åºåºä¸¤ä¸ª tab èµ°æ£å¸¸å页ï¼å«ç¨å¤§ `size` å æ°æ®**ãè§ Â§2.1ï¼`data.total` å°±æ¯æ»æ¡æ°ï¼ç¿»é¡µå³å¯ãåºå tab å 为æ¯ä¸è¡ä¸ä¸ªè§æ ¼çèåç»æï¼ä¿ç `size=100` 没é®é¢ã --- ## 8. èè°èªæ¥æ¸ å - [ ] åºå详æ åå°ãå ¥åºè®°å½ãtab æ¶æè¯·æ± `/stockInRecord/listPage`ï¼è½ååºè¯¥è§æ ¼å ¥åºè®°å½ï¼ä¸ååªæä¸æ¡ï¼ - [ ] åºå详æ åå°ãåºåºè®°å½ãtab æ¶æè¯·æ± `/stockOutRecord/listPage`ï¼è½ååºè¯¥è§æ ¼åºåºè®°å½ - [ ] ä¸ä¸ª tab åèªç¬ç«å页ï¼åç¿»åç页ï¼äºä¸å½±åï¼`data.total` æ¾ç¤ºçæ¯è¯¥ tab çç宿»æ¡æ° - [ ] å tab æ¶å¸¦ `productModelId`ï¼+ `topParentProductId`ï¼ï¼ä¸è¦æ¼ä¼ å¯¼è´æ¥æå ¨äº§åæ çæ°æ® - [ ] ä¸åå 容äºä¸ä¸²ï¼åºåæ°éä¸å ¥åºè®°å½æ¡æ°/æ°éè½å¯¹ä¸ï¼276/407ï¼ä¸¤æ¹ 32.54 + 32.80 = 65.34ï¼ - [ ] å ¥åºè®°å½æ¯è¡æ¹å·æ¯å个æ¹å·ï¼ä¸æ¯éå·æ¼æ¥ä¸² - [ ] ä¼ `productModelId` åç»æåªå«è¯¥è§æ ¼ï¼ä¸ä¼ æ¶ä¸æ¹å¨åä¸è´ï¼åå½å ¥åºç®¡çãåºåºç®¡ç两个åè¡¨é¡µï¼ - [ ] å ¥åºç®¡ç / åºåºç®¡çèåå表页翻页ãæäº§åå/è§æ ¼/æ¹å·æç´¢åæ£å¸¸ï¼æ¬æ¬¡æ¹å¨æªå½±åï¼ - [ ] å¾ å®¡æ ¸çå ¥åº/åºåºè®°å½å¨è¯¦æ éçå±ç¤ºå£å¾å·²ä¸éæ±æ¹ç¡®è®¤ï¼å ¨å±ç¤º or åªçå·²å®¡æ ¸ï¼ doc/20260922_ÓÍÆ·³öÈë¿âͼƬURLʧЧÐÞ¸´ËµÃ÷.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,151 @@ # æ²¹ååºå ¥åºå¾ç URL 失æä¿®å¤è¯´æ æ´æ°æ¶é´ï¼2026-09-22 éç¨æ¨¡åï¼æ²¹åå ¥åºï¼`/inventoryManagement/stockManagement` å ¥åºå¼¹çªï¼ãæ²¹ååºåºï¼åºåºå¼¹çªï¼ãåºå详æ ãå ¥åºç®¡çãåºåºç®¡ç ## 1. ç°è±¡ æ²¹ååºå ¥åºåæ®ä¸çç §çï¼å¸æ²¹/è£ æ²¹/ç£ åï¼å¨æ°é¡µé¢æå¼æ¶å ¨é¨å è½½å¤±è´¥ï¼æç¤ºé¾æ¥å¤±æã ## 2. æ ¹å åºå ¥åºç 4 个å¾çåæ®µï¼`stock_out_record.loading_photos` / `pound_photos`ã`stock_in_record.unload_photos` / `pound_photos`ï¼**åç䏿¯ blob idï¼èæ¯ä¸ä¼ æ¥å£è¿åç `StorageBlobVO` JSON å¿«ç §**ï¼ ```json [{ "id":340, "resourceKey":"42e5de...", "uidFilename":"81af99d2-..._粤k.jpg", "path":"2026/0922", "previewURL":"http://36.213.90.123:9018/prod-api/common/preview/<uid>?token=<JWT>", "url":"â¦?token=<JWT>", "downloadURL":"â¦/download/<uid>?token=<JWT>" }] ``` `/common/upload`ï¼`CommonController.java:39`ï¼`isPublic=false`ï¼ç¾åç `?token=<JWT>` æ**䏤鿶æ**ï¼ | æ¶æ | æ¥æº | | --- | --- | | 2 å°æ¶ | JWT `exp`ï¼`FileUtil.buildSignedUrl:758` é»è®¤ 120 åé | | ä½¿ç¨æ¬¡æ° | Redis 计æ°ï¼`FileUtil.validateTokenUsage:796`ï¼`useLimit` é»è®¤ 10 次 | äºæ¯å¿«ç §ä¸è½åºå°±æäºãæ»é¾æ¥ãï¼2 å°æ¶åè¿æï¼æé¢è§ 10 次å失æï¼æ Redis 飿¬¡ key è¢«æ¸ çåç«å»æ¥ã龿¥å·²è¿ææè¾¾å°ä½¿ç¨æ¬¡æ°å¤±æãã å端侧çç´æ¥åå ï¼`AttachmentUpload/image/index.vue` å·²æä¾ `permanent` å¼å ³ï¼èµ° `/common/public/upload`ï¼æ¿ `?publicKey=` æ°¸ä¹ å°åï¼ï¼ä½åºå ¥åºç 4 个 `ImageUpload` **齿²¡ä¼ `permanent`**ï¼é»è®¤èµ°äºä¼è¿æç `/common/upload`ï¼2026-09-22 已修ï¼è§ §6.1ï¼ï¼ | æä»¶ | ä¸ä¼ ç¹ | | --- | --- | | `OilStockInDialog.vue` | 叿²¹æç §ï¼`unloadPhotos`ï¼ãç£ åï¼`poundPhotos`ï¼ | | `OilStockOutDialog.vue` | è£ æ²¹æç §ï¼`loadingPhotos`ï¼ãç£ åï¼`poundPhotos`ï¼ | ## 3. å½±åèå´ï¼çº¿ä¸åº `product-inventory-management-rbhb`ï¼2026-09-22 æ ¸å¯¹ï¼ åªæ 8 ä¸ªåæ®µå¼ãå ± 11 å¼ å¾ï¼ | 表 | å | è®°å½ id | å¾çæ° | | --- | --- | --- | --- | | `stock_out_record` | `loading_photos` | 257 | 2 | | `stock_out_record` | `pound_photos` | 257 | 1 | | `stock_in_record` | `unload_photos` | 235 / 236 / 238 | 2 / 2 / 1 | | `stock_in_record` | `pound_photos` | 235 / 236 / 238 | 1 / 1 / 1 | ## 4. å·²åçæ°æ®ä¿®å¤ï¼çº¿ä¸åºå·²æ§è¡ï¼ ææ¯ä¸ª URL ç `?token=<JWT>` 就尿¹æ `?publicKey=<åä¸ä¸ª JSON 对象èªå·±ç resourceKey>`ã`StorageBlobServiceImpl.getPublicFile:114` åªæ ¡éª `uid_filename + resource_key` 两åï¼å½ä¸å³æ°¸ä¹ å¯è®¿é®ï¼ ``` â¦/common/preview/81af99d2-â¦_粤k.jpg?publicKey=42e5de4cf76a49d5ba05a7021ed38eb9 ``` æ¹åæ¹å¼ï¼å¯¹æ¯ä¸ªåå¥ 3 è½® `REGEXP_REPLACE`ï¼æ¯ä¸ªå¯¹è±¡æ `previewURL` / `url` / `downloadURL` ä¸ä¸ª token å°åï¼3 è½®æ£å¥½éä¸ªæ¿æ¢ï¼ï¼åªå¤ç `like '%?token=%'` çè¡ï¼å¯é夿§è¡ï¼ ```sql update stock_in_record set unload_photos = regexp_replace( regexp_replace( regexp_replace(unload_photos, '("resourceKey":"([0-9a-f]{32})")(.*?)[?]token=[A-Za-z0-9._-]+', '$1$3?publicKey=$2'), '("resourceKey":"([0-9a-f]{32})")(.*?)[?]token=[A-Za-z0-9._-]+', '$1$3?publicKey=$2'), '("resourceKey":"([0-9a-f]{32})")(.*?)[?]token=[A-Za-z0-9._-]+', '$1$3?publicKey=$2') where id > 0 and unload_photos is not null and unload_photos <> '' and unload_photos like '%?token=%'; -- åæ³å¤ç stock_in_record.pound_photosãstock_out_record.loading_photosãstock_out_record.pound_photos ``` **代价**ï¼è¿äº URL 仿¤é¿æææï¼çå `/common/public/upload` çå ¬å¼è¯ä¹ï¼ï¼ç¥é龿¥å³å¯è®¿é®ââä¸é¡¹ç®éãä¸»æ°æ®å¾çãçæ¢æå£å¾ä¸è´ã ### 4.1 å¤ä»½ä¸åæ» æ¹åä¸å¯éï¼å JWT æ æ³é建ï¼ï¼æ§è¡åå·²æ 8 个å弿´ä¸²çå¨ååºå¤ä»½è¡¨ `bak_20260922_photo_token`ï¼ | å | å«ä¹ | | --- | --- | | `src_table` / `src_id` / `src_column` | æ¥æºå®ä½ | | `orig_value` | æ¹ååçåå§æ´ä¸² | | `backup_time` | å¤ä»½æ¶é´ | åæ»ç¤ºä¾ï¼ ```sql update stock_in_record s join bak_20260922_photo_token b on b.src_table = 'stock_in_record' and b.src_id = s.id and b.src_column = 'unload_photos' set s.unload_photos = b.orig_value; ``` 确认æ éåæ»åï¼ç±ä¸å¡æ¹èªè¡ `drop table bak_20260922_photo_token;`ã ### 4.2 éªè¯ç»æ | 项 | ç»æ | | --- | --- | | `?token=` æ®ç | 4 个åå ¨é¨ 0 | | `?publicKey=` æ°é | ä¸å¯¹è±¡æ° à 3 ä¸è´ï¼6/3/15/9ï¼ | | ä¸ `storage_blob` å¹é | 11 å¼ å¾å ¨é¨æ `uid_filename + resource_key` å½ä¸ï¼æ å¤å¿å¼ç¨ | | 宿µæå | 11/11 è¿å `200 image/jpeg`ï¼åèæ°ä¸ `storage_blob.byte_size` ä¸è´ | ## 5. å端注æäºé¡¹ 1. åéå¾ç**å·²æ¢å¤**ï¼éæ°æå¼è¯¦æ /å表å³å¯ï¼è¥æµè§å¨ç¼åè¿å¤±è´¥ç»æï¼å¼ºå¶å·æ°ä¸æ¬¡ã 2. è¿åå¼ä»æ¯åæ¥ç JSON æ°ç»ç»æï¼åæ®µåæªåï¼`previewURL` / `url` / `downloadURL` / `uidFilename` çï¼ï¼**æ¶è´¹ç«¯**ï¼å表ã详æ ãé¢è§ï¼ä¸éè¦æ¹ä»£ç ï¼ä¸ä¼ ç«¯è¦æ¹ï¼è§ §6.1ã ## 6. 代ç å±ä¿®å¤ï¼2026-09-22 å·²æ¹ï¼ æ°æ®ä¿®å¤åªæ¯æ¢è¡ââä¸å µä½ä¸ä¼ ç«¯ï¼æ°ç §çç §æ · 2 å°æ¶ååæ»é¾ãä¸ä¼ 端ä¸è¯»åç«¯çæ¶å£é½å¨ 2026-09-22 ä¸å¹¶æ¹æã ### 6.1 å端ï¼å·²æ¹ï¼4 个 `ImageUpload` è¡¥ `permanent`ï¼ - `src/views/inventoryManagement/stockManagement/OilStockInDialog.vue`ï¼å¸æ²¹æç §ãç£ å - `src/views/inventoryManagement/stockManagement/OilStockOutDialog.vue`ï¼è£ æ²¹æç §ãç£ å `AttachmentUpload/image/index.vue` ç `permanent` 忝ä¼ï¼ä¸ä¼ æ¹èµ° `uploadPublicFile`ï¼`/common/public/upload`ï¼ï¼å¹¶æ `url` åæ `previewURL`ãå端 `getStorageBlob(..., isPublic=true)` ç¨ `expired=-1` çæ `previewURL` / `downloadURL`ï¼ä¸¤ä¸ªé½æ¯æ°¸ä¹ å°åï¼ä¸ååºé `url` æ¬æ¥å°±æ¯ç©ºãç±å端补æ `previewURL`ââæä»¥è½åºçæ´ä¸ªå¯¹è±¡ä¸åå«ä»»ä½ tokenã 两æ¡ååºé¾è·¯é½æ ¸å¯¹è¿ï¼ä¸ä¼è¢«æ¹ååå»ï¼ - å ¥åºå¼¹çªæäº¤åå§æ°ç»ï¼å端 `StockInventoryServiceImpl` ç¨ `JSON.toJSONString` 转åç¬¦ä¸²å ¥åºï¼ - åºåºå¼¹çªèªå·± `JSON.stringify`ã åºå ¥åºåªæè¿ 4 å¤ä¸ä¼ ç¹ãå¦å¤ä¸¤å¤ `ImageUpload` è½åºæ¹å¼ä¸åãä¸åå½±åï¼`salesLedger/index.vue:1215`ã`deliveryLedger/index.vue:250` èµ° `storageBlobDTOs` â `saveStorageAttachment` åçæ¯ blob **id**ï¼URL ç±è¯»å端 `getStorageBlobVOs*` éæ°ç¾åï¼`vehicle`ã`ArrivalDialog` å·²ç»æ¯ `permanent`ã ### 6.2 å端ï¼å·²æ¹ 1 å¤ï¼`refreshPhotoUrls` å æ°¸ä¹ å¤æï¼ `StockInventoryServiceImpl.getBatchNoQty:511-521` ä¼å¯¹ç §çå读æ¶éç¾ï¼`refreshPhotoUrls:534`ï¼ãå®è° `buildSignedUrl(vo, "/preview/", null)`ï¼`expired=null` èµ°é»è®¤ 120 åé忝ââ**ä¼ææ°¸ä¹ publicKey å°åéæ°é级æ 2 å°æ¶ token**ãæ¢ç¶ç°å¨åºéçåæ°ä¼ ç齿¯æ°¸ä¹ å°åï¼è¿ä¸ªæ¹æ³å¿ é¡»å 夿åç¾ï¼ ```java for (StorageBlobVO vo : list) { // å·²ç»æ¯ publicKey æ°¸ä¹ å°åçä¿æä¸å¨ï¼éç¾ä¼æå®é级å 2 å°æ¶å¤±æç token if (StringUtils.hasText(vo.getPreviewURL()) && vo.getPreviewURL().contains("publicKey=")) { continue; } String previewUrl = fileUtil.buildSignedUrl(vo, "/preview/", null); vo.setPreviewURL(previewUrl); vo.setUrl(previewUrl); vo.setDownloadURL(fileUtil.buildSignedUrl(vo, "/download/", null)); } ``` ææ¯ä¸ª VO åç¬å¤æï¼ä¸æ¯æ´ä¸²å¤æï¼ï¼è¿æ ·ãè token å¿«ç § + æ°æ°¸ä¹ å°åãæ··åçè®°å½éï¼èçé£å å¼ ä»ä¼è¢«éç¾æææå°åã **ä¸åéè¦ç» `/stockInRecord/listPage`ã`/stockOutRecord/listPage` å éç¾**ï¼è¿ä¸¤æ¡é¾è·¯åæ ·è¿ååºéçå¼ï¼èåºéç°å¨ï¼åéå·²å· + æ°å¢èµ°æ°¸ä¹ ï¼å°±æ¯æ°¸ä¹ å°åï¼ç´æ¥å¯ç¨ã ### 6.3 åç»å¯é å½»åºæ¶é¤ãURL å¿«ç §è½åºãè¿ä¸ªæ ¹å ï¼å¯æ¹æåºéåªå blob idãè¯»åæ¶ç»ä¸ç¨ `getStorageBlobVOs*` éç¾ï¼ä¸ `storage_attachment` é£å¥ä¸è´ï¼ãæ¹å¨é¢è¾å¤§ï¼éå¿ éï¼å¦æã src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -545,6 +545,10 @@ return photos; } for (StorageBlobVO vo : list) { // å·²ç»æ¯ publicKey æ°¸ä¹ å°åçä¿æä¸å¨ï¼éç¾ä¼æå®é级å 2 å°æ¶å¤±æç token if (StringUtils.hasText(vo.getPreviewURL()) && vo.getPreviewURL().contains("publicKey=")) { continue; } String previewUrl = fileUtil.buildSignedUrl(vo, "/preview/", null); vo.setPreviewURL(previewUrl); vo.setUrl(previewUrl); src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -294,19 +294,21 @@ LIMIT 5 </select> <!-- éè´ååå¸ï¼ä¸ãå产åéå®éé¢åæãåå£å¾ï¼ç´æ¥æéè´æç»ä¸çåç±»èåã ä¸è½åæäº§åæ ãåææãåæ è¿æ»¤ ââ éè´å°è´¦å®é ç»è®°çåç±»ï¼æ´æ²¹ãçç«å¨ï¼åå«æå¨ ãæå/æåæ²¹ãã设å¤è®¾æ½/å ¬å ±å®å ¨è®¾å¤ãä¸ï¼æåæ è¿æ»¤ä¼æä¸ºç©º --> <select id="selectRawMaterialPurchaseAnalysis" resultType="java.util.Map"> SELECT pr.product_name AS name, slp.product_category AS name, SUM( slp.tax_inclusive_total_price ) AS value FROM sales_ledger_product slp JOIN product pr ON slp.product_id = pr.id WHERE slp.type = 2 AND pr.parent_id = ( SELECT id FROM product WHERE product_name = 'åææ' ) AND slp.product_category IS NOT NULL AND slp.product_category != '' GROUP BY pr.id, pr.product_name slp.product_category ORDER BY value DESC LIMIT 5 src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -125,6 +125,9 @@ <if test="params.batchNo != null and params.batchNo != ''"> and sir.batch_no like concat('%',#{params.batchNo},'%') </if> <if test="params.productModelId != null and params.productModelId > 0"> and sir.product_model_id = #{params.productModelId} </if> <if test="params.type != null and params.type != ''"> and sir.type = #{params.type} </if> src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -604,13 +604,25 @@ AND create_time <= #{endDate}) AS combined_counts </select> <!-- åºå ¥åºè¶å¿ï¼äº§ååç±»å¿ é¡»éå½åæ´æ£µåæ ã äº§åæ æ¯ã大类 -> åç±» -> å ·ä½äº§åãä¸å±ï¼äº§ååå·ï¼product_modelï¼æå¨å¶å产åä¸ï¼ åªæ¯å¯¹ç´æ¥åèç¹ï¼p.parent_id = rootï¼æ°¸è¿å½ä¸ä¸å°åå·ï¼è¶å¿å¾æä¸ºç©ºã éå½ CTE å卿¬å·å ï¼è®©è¯å¥ä»ä»¥ SELECT å¼å¤´ï¼æ°æ®æéæ¦æªå¨ç §å¸¸å¯¹ stock_in_record çæ --> <select id="selectDailyStockInCounts" resultType="java.util.Map"> SELECT DATE(sir.create_time) AS date, SUM(sir.stock_in_num) AS count FROM stock_in_record sir JOIN product_model pm ON sir.product_model_id = pm.id JOIN product p ON pm.product_id = p.id WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId}) WHERE p.id IN (WITH RECURSIVE product_tree AS (SELECT id FROM product WHERE id = #{rootCategoryId} UNION ALL SELECT p2.id FROM product p2 JOIN product_tree pt ON p2.parent_id = pt.id) SELECT id FROM product_tree) AND sir.create_time >= #{startDate} AND sir.create_time <= #{endDate} GROUP BY DATE(sir.create_time) @@ -623,7 +635,15 @@ FROM stock_out_record sor JOIN product_model pm ON sor.product_model_id = pm.id JOIN product p ON pm.product_id = p.id WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId}) WHERE p.id IN (WITH RECURSIVE product_tree AS (SELECT id FROM product WHERE id = #{rootCategoryId} UNION ALL SELECT p2.id FROM product p2 JOIN product_tree pt ON p2.parent_id = pt.id) SELECT id FROM product_tree) AND sor.create_time >= #{startDate} AND sor.create_time <= #{endDate} GROUP BY DATE(sor.create_time) src/main/resources/mapper/stock/StockOutRecordMapper.xml
@@ -61,6 +61,9 @@ <if test="params.batchNo != null and params.batchNo != ''"> and sor.batch_no like concat('%',#{params.batchNo},'%') </if> <if test="params.productModelId != null and params.productModelId > 0"> and sor.product_model_id = #{params.productModelId} </if> <if test="params.type != null and params.type != ''"> and sor.type = #{params.type} </if>