2026-06-01 f80eee649f269eb61f15c7d0d2e282146eaaf9ef
feat(home): 新增上月销售采购金额统计功能

- 在 HomeBusinessDto 中添加 lastMonthSaleMoney 和 lastMonthPurchaseMoney 字段
- 实现上月销售金额查询逻辑,统计 sales_ledger 表中上月 contract_amount 总和
- 实现上月采购金额查询逻辑,统计 purchase_ledger 表中上月 contract_amount 总和
- 创建前端联调文档说明新增字段的使用方法和数据口径
- 保持原有功能不变,仅新增字段支持环比趋势展示
已添加1个文件
已修改2个文件
135 ■■■■■ 文件已修改
doc/20260601_home_business_上月数据_前端联调文档.md 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/20260601_home_business_ÉÏÔÂÊý¾Ý_ǰ¶ËÁªµ÷Îĵµ.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
# /home/business æŽ¥å£æ–°å¢žä¸Šæœˆæ•°æ® â€” å‰ç«¯è”调文档
## å˜æ›´æ¦‚è¿°
`GET /home/business` æŽ¥å£åœ¨åŽŸæœ‰å­—æ®µåŸºç¡€ä¸Šæ–°å¢ž **上月销售金额** å’Œ **上月采购金额** ä¸¤ä¸ªå­—段,前端可直接用于展示环比趋势。
---
## æŽ¥å£ä¿¡æ¯
| é¡¹ç›® | å†…容 |
|------|------|
| æŽ¥å£åœ°å€ | `/home/business` |
| è¯·æ±‚方式 | `GET` |
| æ˜¯å¦è®¤è¯ | æ˜¯ |
---
## å“åº”参数
### æ–°å¢žå­—段
| å­—段名 | ç±»åž‹ | è¯´æ˜Ž |
|--------|------|------|
| `lastMonthSaleMoney` | `String` | ä¸Šæœˆé”€å”®åˆåŒé‡‘额(元),保留两位小数,如 `"150000.00"` |
| `lastMonthPurchaseMoney` | `String` | ä¸Šæœˆé‡‡è´­åˆåŒé‡‘额(元),保留两位小数,如 `"80000.00"` |
### å®Œæ•´å“åº”
```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "monthSaleMoney": "200000.00",
    "lastMonthSaleMoney": "150000.00",
    "monthSaleHaveMoney": "0.00",
    "monthPurchaseMoney": "100000.00",
    "lastMonthPurchaseMoney": "80000.00",
    "monthPurchaseHaveMoney": "0.00",
    "inventoryNum": "5000.00",
    "todayInventoryNum": "120.00"
  }
}
```
### æ‰€æœ‰å­—段一览
| å­—段名 | ç±»åž‹ | è¯´æ˜Ž |
|--------|------|------|
| `monthSaleMoney` | `String` | æœ¬æœˆé”€å”®é‡‘额 |
| `lastMonthSaleMoney` | **`String`(新增)** | ä¸Šæœˆé”€å”®é‡‘额 |
| `monthSaleHaveMoney` | `String` | æœ¬æœˆé”€å”®æœªå¼€ç¥¨é‡‘额(当前固定 `0.00`) |
| `monthPurchaseMoney` | `String` | æœ¬æœˆé‡‡è´­é‡‘额 |
| `lastMonthPurchaseMoney` | **`String`(新增)** | ä¸Šæœˆé‡‡è´­é‡‘额 |
| `monthPurchaseHaveMoney` | `String` | æœ¬æœˆé‡‡è´­æœªå¼€ç¥¨é‡‘额(当前固定 `0.00`) |
| `inventoryNum` | `String` | å½“前库存总量 |
| `todayInventoryNum` | `String` | ä»Šæ—¥å…¥åº“数量 |
---
## æ•°æ®å£å¾„
| å­—段 | æ•°æ®æ¥æº | ç»Ÿè®¡å£å¾„ |
|------|---------|---------|
| `monthSaleMoney` | `sales_ledger` è¡¨ | `entry_date` åœ¨æœ¬æœˆ1日~下月1日之间的 `contract_amount` åˆè®¡ |
| `lastMonthSaleMoney` | `sales_ledger` è¡¨ | `entry_date` åœ¨ä¸Šæœˆ1日~本月1日之间的 `contract_amount` åˆè®¡ |
| `monthPurchaseMoney` | `purchase_ledger` è¡¨ | `entry_date` åœ¨æœ¬æœˆ1日~下月1日之间的 `contract_amount` åˆè®¡ |
| `lastMonthPurchaseMoney` | `purchase_ledger` è¡¨ | `entry_date` åœ¨ä¸Šæœˆ1日~本月1日之间的 `contract_amount` åˆè®¡ |
---
## å‰ç«¯ä½¿ç”¨å»ºè®®
### çŽ¯æ¯”å±•ç¤º
```javascript
// è®¡ç®—环比变化
const saleGrowth = lastMonthSaleMoney > 0
  ? ((monthSaleMoney - lastMonthSaleMoney) / lastMonthSaleMoney * 100).toFixed(1)
  : 100;
const purchaseGrowth = lastMonthPurchaseMoney > 0
  ? ((monthPurchaseMoney - lastMonthPurchaseMoney) / lastMonthPurchaseMoney * 100).toFixed(1)
  : 100;
```
### è¶‹åŠ¿ç®­å¤´
- `saleGrowth > 0` â†’ çº¢è‰²å‘上箭头 (↑)
- `saleGrowth < 0` â†’ ç»¿è‰²å‘下箭头 (↓)
- `saleGrowth === 0` â†’ ç°è‰²æŒå¹³ (→)
---
## æ³¨æ„äº‹é¡¹
1. **类型为 String**:金额字段均为字符串,保留两位小数,计算环比时需用 `parseFloat()` è½¬æ¢
2. **默认值**:无数据时返回 `"0.00"`,不会返回 `null`
3. **未开票字段**:`monthSaleHaveMoney` å’Œ `monthPurchaseHaveMoney` å½“前固定返回 `"0.00"`,后续迭代会接入实际数据
4. **向后兼容**:仅新增字段,原有字段不变,已有前端功能不受影响
src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java
@@ -16,12 +16,18 @@
    @Schema(description = "本月销售金额")
    private String monthSaleMoney = "0.00";
    @Schema(description = "上月销售金额")
    private String lastMonthSaleMoney = "0.00";
    @Schema(description = "本月销售未开票金额")
    private String monthSaleHaveMoney = "0.00";
    @Schema(description = "本月采购金额")
    private String monthPurchaseMoney = "0.00";
    @Schema(description = "上月采购金额")
    private String lastMonthPurchaseMoney = "0.00";
    @Schema(description = "本月采购未开票金额")
    private String monthPurchaseHaveMoney = "0.00";
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -179,6 +179,34 @@
            homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString());
            homeBusinessDto.setMonthPurchaseHaveMoney(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // ä¸Šæœˆé”€å”®é‡‘额
        YearMonth lastMonth = currentMonth.minusMonths(1);
        LambdaQueryWrapper<SalesLedger> lastMonthSalesWrapper = new LambdaQueryWrapper<>();
        lastMonthSalesWrapper.ge(SalesLedger::getEntryDate, lastMonth.atDay(1).atStartOfDay())
                .lt(SalesLedger::getEntryDate, lastMonth.plusMonths(1).atDay(1).atStartOfDay());
        List<SalesLedger> lastMonthSalesLedgers = salesLedgerMapper.selectList(lastMonthSalesWrapper);
        if (!CollectionUtils.isEmpty(lastMonthSalesLedgers)) {
            BigDecimal lastMonthContractAmount = lastMonthSalesLedgers.stream()
                    .map(SalesLedger::getContractAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            homeBusinessDto.setLastMonthSaleMoney(lastMonthContractAmount.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // ä¸Šæœˆé‡‡è´­é‡‘额
        LambdaQueryWrapper<PurchaseLedger> lastMonthPurchaseWrapper = new LambdaQueryWrapper<>();
        lastMonthPurchaseWrapper.ge(PurchaseLedger::getEntryDate, lastMonth.atDay(1).atStartOfDay())
                .lt(PurchaseLedger::getEntryDate, lastMonth.plusMonths(1).atDay(1).atStartOfDay());
        List<PurchaseLedger> lastMonthPurchaseLedgers = purchaseLedgerMapper.selectList(lastMonthPurchaseWrapper);
        if (!CollectionUtils.isEmpty(lastMonthPurchaseLedgers)) {
            BigDecimal lastMonthPurchaseAmount = lastMonthPurchaseLedgers.stream()
                    .map(PurchaseLedger::getContractAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            homeBusinessDto.setLastMonthPurchaseMoney(lastMonthPurchaseAmount.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // ç»Ÿè®¡åº“å­˜
        BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal();
        homeBusinessDto.setInventoryNum(stockQuantityTotal.setScale(2, RoundingMode.HALF_UP).toString());