Ver Fonte

feat(property): 添加收据和退款统计报表功能

- 在收据信息中新增操作人字段并保存到数据库
- 添加楼宇和楼层信息到收据相关视图对象
- 实现按年、按月、按日统计收据和退款的报表功能
- 新增收据和退款的日报表、月报表、年报表接口
- 配置生产环境激活配置
- 新增相关的报表数据传输对象和SQL映射
- 实现收据和退款统计数据的按资产类型筛选功能
- 重构部分查询方法以支持统计报表需求
林仔 há 2 meses atrás
pai
commit
aebc29b9ec
24 ficheiros alterados com 838 adições e 12 exclusões
  1. 37 0
      src/main/java/com/zksy/controller/property/AReceiptInfoController.java
  2. 40 0
      src/main/java/com/zksy/controller/property/ARefundController.java
  3. 6 0
      src/main/java/com/zksy/property/domain/AReceiptInfo.java
  4. 5 0
      src/main/java/com/zksy/property/domain/ARefund.java
  5. 49 0
      src/main/java/com/zksy/property/domain/vo/AReceiptInfoReportDayVo.java
  6. 52 0
      src/main/java/com/zksy/property/domain/vo/AReceiptInfoReportVo.java
  7. 50 0
      src/main/java/com/zksy/property/domain/vo/ARefundReportDayVo.java
  8. 41 0
      src/main/java/com/zksy/property/domain/vo/ARefundReportVo.java
  9. 2 0
      src/main/java/com/zksy/property/domain/vo/CanBeGetReceiptVo.java
  10. 2 0
      src/main/java/com/zksy/property/domain/vo/CanBeGetReturnReceiptVo.java
  11. 21 0
      src/main/java/com/zksy/property/mapper/AReceiptInfoMapper.java
  12. 20 0
      src/main/java/com/zksy/property/mapper/ARefundMapper.java
  13. 6 0
      src/main/java/com/zksy/property/service/AReceiptInfoService.java
  14. 6 0
      src/main/java/com/zksy/property/service/ARefundService.java
  15. 5 0
      src/main/java/com/zksy/property/service/impl/AContractInfoServiceImpl.java
  16. 137 2
      src/main/java/com/zksy/property/service/impl/AReceiptInfoServiceImpl.java
  17. 128 2
      src/main/java/com/zksy/property/service/impl/ARefundServiceImpl.java
  18. 1 1
      src/main/java/com/zksy/property/service/impl/ARentalContractServiceImpl.java
  19. 1 1
      src/main/resources/application.yml
  20. 118 1
      src/main/resources/mapper/property/AReceiptInfoMapper.xml
  21. 109 1
      src/main/resources/mapper/property/ARefundMapper.xml
  22. BIN
      src/main/resources/templates/1.docx
  23. BIN
      src/main/resources/templates/4.docx
  24. 2 4
      src/test/java/com/zksy/property/service/impl/AContractInfoServiceImplTest.java

+ 37 - 0
src/main/java/com/zksy/controller/property/AReceiptInfoController.java

@@ -5,6 +5,7 @@ import com.zksy.property.service.AReceiptInfoService;
 import com.zksy.utils.AjaxResult;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -81,5 +82,41 @@ public class AReceiptInfoController {
     public AjaxResult getExistingYears() {
         return AjaxResult.success(service.getExistingYears());
     }
+    /**
+     * 获取收据汇总报表
+     * @return 汇总数据列表
+     */
+/*    @GetMapping("/getReceiptReport")
+    @ApiOperation("获取收据汇总报表(按年/按月)")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "int", defaultValue = "2025"),
+            @ApiImplicitParam(name = "month", value = "月份", required = false, dataType = "int", defaultValue = "11")
+    })
+    public AjaxResult getReceiptReport(Integer year, Integer month) {
+        return AjaxResult.success(service.getReceiptReport(year, month));
+    }*/
+    @GetMapping("/receipt/stat/year")
+    @ApiOperation("按年统计收据金额(返回1-12月数据)")
+    public AjaxResult statByYear(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statReceiptDetailByYear(year,assetType));
+    }
 
+    @GetMapping("/receipt/stat/month")
+    @ApiOperation("按月统计收据金额(返回当月所有日期数据)")
+    public AjaxResult statByMonth(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("月份,1-12") @RequestParam Integer month,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statReceiptDetailByMonth(year, month,assetType));
+    }
+    @GetMapping("/receipt/stat/day")
+    @ApiOperation("按月统计收据金额(月详情)")
+    public AjaxResult statByDay(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("月份,1-12") @RequestParam Integer month,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statReceiptDetailByDay(year, month,assetType));
+    }
 }

+ 40 - 0
src/main/java/com/zksy/controller/property/ARefundController.java

@@ -5,6 +5,7 @@ import com.zksy.property.service.ARefundService;
 import com.zksy.utils.AjaxResult;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -81,5 +82,44 @@ public class ARefundController {
     public AjaxResult getExistingRefundYears() {
         return AjaxResult.success(service.getExistingRefundYears());
     }
+    /**
+     * 获取退款汇总报表
+     * @param year 年份(必填)
+     * @param month 月份(可选,1-12)
+     * @return 汇总数据列表
+     */
+/*    @GetMapping
+    @ApiOperation("获取退款汇总报表(按年/按月)")
+    public AjaxResult getRefundReport(
+            @ApiParam(value = "年份(必填,如2025)", required = true, example = "2025")
+            @RequestParam Integer year,
+            @ApiParam(value = "月份(可选,1-12,不传则按年查询)", example = "11")
+            @RequestParam(required = false) Integer month
+    ) {
+        return AjaxResult.success(service.getRefundReport(year, month));
+    }*/
+    @GetMapping("/refund/stat/year")
+    @ApiOperation("按年统计退款金额(返回1-12月数据)")
+    public AjaxResult statRefundByYear(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statRefundDetailByYear(year,assetType));
+    }
 
+    @GetMapping("/refund/stat/month")
+    @ApiOperation("按月统计退款金额(返回当月所有日期数据)")
+    public AjaxResult statRefundByMonth(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("月份,1-12") @RequestParam Integer month,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statRefundDetailByMonth(year, month,assetType));
+    }
+    @GetMapping("/refund/stat/day")
+    @ApiOperation("按月统计退款金额(月详情)")
+    public AjaxResult statRefundByDay(
+            @ApiParam("年份,如2024") @RequestParam Integer year,
+            @ApiParam("月份,1-12") @RequestParam Integer month,
+            @ApiParam("输入:公租房/创新创业基地/厂房") @RequestParam String assetType) {
+        return AjaxResult.success(service.statRefundDetailByDay(year, month,assetType));
+    }
 }

+ 6 - 0
src/main/java/com/zksy/property/domain/AReceiptInfo.java

@@ -93,6 +93,12 @@ public class AReceiptInfo implements Serializable {
     @ApiModelProperty(value = "收款事由")
     private String receiptReason;
 
+    /**
+     * 操作人
+     */
+    @ApiModelProperty(value = "操作人")
+    private  String operator;
+
     /**
      * 附件url
      */

+ 5 - 0
src/main/java/com/zksy/property/domain/ARefund.java

@@ -68,6 +68,11 @@ public class ARefund implements Serializable {
      */
     @ApiModelProperty(value = "合计")
     private BigDecimal totalAmount;
+    /**
+     * 操作人
+     */
+    @ApiModelProperty(value = "操作人")
+    private String operator;
 
     /**
      * 生成日期

+ 49 - 0
src/main/java/com/zksy/property/domain/vo/AReceiptInfoReportDayVo.java

@@ -0,0 +1,49 @@
+package com.zksy.property.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 收据信息报表
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class AReceiptInfoReportDayVo{
+    @ApiModelProperty(value = "收取时间")
+    private String receiptTime;
+
+    @ApiModelProperty(value = "房租")
+    private BigDecimal rent;
+
+    @ApiModelProperty(value = "押金")
+    private BigDecimal deposit;
+
+    @ApiModelProperty(value = "物业管理费")
+    private BigDecimal propertyFee;
+
+    @ApiModelProperty(value = "水费")
+    private BigDecimal waterFee;
+
+    @ApiModelProperty(value = "电费")
+    private BigDecimal electricityBill;
+
+    @ApiModelProperty(value = "交款单位")
+    private String payer;
+
+    @ApiModelProperty(value = "租金收取时段")
+    private String rentPeriod;
+
+    @ApiModelProperty(value = "经手人(操作人)")
+    private String operator;
+
+    @ApiModelProperty(value = "支付方式")
+    private String payType;
+
+    @ApiModelProperty(value = "收据号")
+    private String receiptCode;
+}

+ 52 - 0
src/main/java/com/zksy/property/domain/vo/AReceiptInfoReportVo.java

@@ -0,0 +1,52 @@
+package com.zksy.property.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 收据信息报表
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class AReceiptInfoReportVo{
+    /**
+     * 时间
+     */
+    @ApiModelProperty(value = "时间")
+    private String receiptTime;
+
+    /**
+     * 租金
+     */
+    @ApiModelProperty(value = "租金")
+    private BigDecimal rent;
+
+    /**
+     * 押金
+     */
+    @ApiModelProperty(value = "押金")
+    private BigDecimal deposit;
+    /**
+     * 物业费
+     */
+    @ApiModelProperty(value = "物业费")
+    private BigDecimal propertyFee;
+
+    /**
+     * 水费
+     */
+    @ApiModelProperty(value = "水费")
+    private BigDecimal waterFee;
+
+    /**
+     * 电费
+     */
+    @ApiModelProperty(value = "电费")
+    private BigDecimal electricityBill;
+
+}

+ 50 - 0
src/main/java/com/zksy/property/domain/vo/ARefundReportDayVo.java

@@ -0,0 +1,50 @@
+package com.zksy.property.domain.vo;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 退据信息报表
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class ARefundReportDayVo{
+
+    /**
+     * 时间
+     */
+    @ApiModelProperty(value = "时间")
+    private String refundTime;
+    /**
+     * 租户
+     */
+    @ApiModelProperty(value = "租户")
+    private String tenant;
+
+    /**
+     * 押金
+     */
+    @ApiModelProperty(value = "押金")
+    private BigDecimal deposit;
+
+    /**
+     * 租金
+     */
+    @ApiModelProperty(value = "租金")
+    private BigDecimal rent;
+
+    /**
+     * 物业费
+     */
+    @ApiModelProperty(value = "物业费")
+    private BigDecimal propertyFee;
+    /**
+     * 经手人
+     */
+    @ApiModelProperty(value = "经手人")
+    private String operator;
+}

+ 41 - 0
src/main/java/com/zksy/property/domain/vo/ARefundReportVo.java

@@ -0,0 +1,41 @@
+package com.zksy.property.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 退据信息报表
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class ARefundReportVo{
+
+    /**
+     * 时间
+     */
+    @ApiModelProperty(value = "时间")
+    private String refundTime;
+
+    /**
+     * 押金
+     */
+    @ApiModelProperty(value = "押金")
+    private BigDecimal deposit;
+
+    /**
+     * 租金
+     */
+    @ApiModelProperty(value = "租金")
+    private BigDecimal rent;
+
+    /**
+     * 物业费
+     */
+    @ApiModelProperty(value = "物业费")
+    private BigDecimal propertyFee;
+}

+ 2 - 0
src/main/java/com/zksy/property/domain/vo/CanBeGetReceiptVo.java

@@ -11,6 +11,8 @@ import java.math.BigDecimal;
 @AllArgsConstructor
 @NoArgsConstructor
 public class CanBeGetReceiptVo {
+    private String ld;
+    private String lc;
     private String jkdw;
     private BigDecimal zj;
     private BigDecimal yj;

+ 2 - 0
src/main/java/com/zksy/property/domain/vo/CanBeGetReturnReceiptVo.java

@@ -11,6 +11,8 @@ import java.math.BigDecimal;
 @AllArgsConstructor
 @NoArgsConstructor
 public class CanBeGetReturnReceiptVo {
+    private String ld;
+    private String lc;
     private String zh;
     private BigDecimal yj;
 }

+ 21 - 0
src/main/java/com/zksy/property/mapper/AReceiptInfoMapper.java

@@ -3,9 +3,13 @@ package com.zksy.property.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zksy.property.domain.AReceiptInfo;
+import com.zksy.property.domain.vo.AReceiptInfoReportDayVo;
+import com.zksy.property.domain.vo.AReceiptInfoReportVo;
 import com.zksy.property.domain.vo.AReceiptInfoVo;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
 * @author Administrator
 * @description 针对表【a_receipt_info(收据信息表)】的数据库操作Mapper
@@ -19,6 +23,23 @@ public interface AReceiptInfoMapper extends BaseMapper<AReceiptInfo> {
                                                          @Param("payer") String payer,
                                                          @Param("paymentMethod") String paymentMethod,
                                                          @Param("contractNumber") String contractNumber);
+
+    /**
+     * 按年统计收据明细:返回1-12月的租金、押金等明细,receiptTime为"X月"
+     * @param year 统计年份(如2024)
+     * @return 1-12月的明细统计结果
+     */
+    List<AReceiptInfoReportVo> statReceiptByYear(@Param("year") Integer year,@Param("assetType") String assetType);
+
+    /**
+     * 按月统计收据明细:返回当月每日的租金、押金等明细,receiptTime为"yyyy-MM-dd"
+     * @param year 年份(如2024)
+     * @param month 月份(1-12)
+     * @return 当月每日的明细统计结果
+     */
+    List<AReceiptInfoReportVo> statReceiptByMonth(@Param("year") Integer year, @Param("month") Integer month,@Param("assetType") String assetType);
+
+    List<AReceiptInfoReportDayVo> statReceiptByDay(@Param("year") Integer year, @Param("month") Integer month,@Param("assetType") String assetType);
 }
 
 

+ 20 - 0
src/main/java/com/zksy/property/mapper/ARefundMapper.java

@@ -3,9 +3,13 @@ package com.zksy.property.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zksy.property.domain.ARefund;
+import com.zksy.property.domain.vo.ARefundReportDayVo;
+import com.zksy.property.domain.vo.ARefundReportVo;
 import com.zksy.property.domain.vo.ARefundVo;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
 * @author Administrator
 * @description 针对表【a_refund(退款信息表)】的数据库操作Mapper
@@ -18,6 +22,22 @@ public interface ARefundMapper extends BaseMapper<ARefund> {
                                                    @Param("unit") String unit,
                                                    @Param("tenant") String tenant,
                                                    @Param("contractNumber") String contractNumber);
+    /**
+     * 按年统计退款明细:返回1-12月的押金、租金、物业费,refundTime为"X月"
+     * @param year 统计年份(如2024)
+     * @return 1-12月的退款明细统计结果
+     */
+    List<ARefundReportVo> statRefundByYear(@Param("year") Integer year,@Param("assetType") String assetType);
+
+    /**
+     * 按月统计退款明细:返回当月每日的押金、租金、物业费,refundTime为"yyyy-MM-dd"
+     * @param year 年份(如2024)
+     * @param month 月份(1-12)
+     * @return 当月每日的退款明细统计结果
+     */
+    List<ARefundReportVo> statRefundByMonth(@Param("year") Integer year, @Param("month") Integer month,@Param("assetType") String assetType);
+
+    List<ARefundReportDayVo> statRefundByDay(@Param("year") Integer year, @Param("month") Integer month,@Param("assetType") String assetType);
 }
 
 

+ 6 - 0
src/main/java/com/zksy/property/service/AReceiptInfoService.java

@@ -3,6 +3,8 @@ package com.zksy.property.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zksy.property.domain.AReceiptInfo;
+import com.zksy.property.domain.vo.AReceiptInfoReportDayVo;
+import com.zksy.property.domain.vo.AReceiptInfoReportVo;
 import com.zksy.property.domain.vo.AReceiptInfoVo;
 
 import java.math.BigDecimal;
@@ -26,4 +28,8 @@ public interface AReceiptInfoService extends IService<AReceiptInfo> {
     Map<String, BigDecimal> calculateYearlyStatistics();
     // 获取数据库中存在的年份列表
     List<Integer> getExistingYears();
+    List<AReceiptInfoReportVo> getReceiptReport(Integer year, Integer month);
+    List<AReceiptInfoReportVo> statReceiptDetailByYear(Integer year,String assetType);
+    List<AReceiptInfoReportVo> statReceiptDetailByMonth(Integer year, Integer month,String assetType);
+    List<AReceiptInfoReportDayVo> statReceiptDetailByDay(Integer year, Integer month,String assetType);
 }

+ 6 - 0
src/main/java/com/zksy/property/service/ARefundService.java

@@ -3,6 +3,8 @@ package com.zksy.property.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zksy.property.domain.ARefund;
+import com.zksy.property.domain.vo.ARefundReportDayVo;
+import com.zksy.property.domain.vo.ARefundReportVo;
 import com.zksy.property.domain.vo.ARefundVo;
 
 import java.math.BigDecimal;
@@ -25,4 +27,8 @@ public interface ARefundService extends IService<ARefund> {
     Map<String, BigDecimal> calculateQuarterlyRefundStatistics(int year);
     Map<String, BigDecimal> calculateYearlyRefundStatistics();
     List<Integer> getExistingRefundYears();
+    List<ARefundReportVo> getRefundReport(Integer year, Integer month);
+    List<ARefundReportVo> statRefundDetailByYear(Integer year,String assetType);
+    List<ARefundReportVo> statRefundDetailByMonth(Integer year, Integer month,String assetType);
+    List<ARefundReportDayVo> statRefundDetailByDay(Integer year, Integer month,String assetType);
 }

+ 5 - 0
src/main/java/com/zksy/property/service/impl/AContractInfoServiceImpl.java

@@ -160,6 +160,7 @@ public class AContractInfoServiceImpl extends ServiceImpl<AContractInfoMapper, A
         if(StringUtils.isNotBlank(dto.getEndDate())){
             receiptInfo.setEndDate(LocalDate.parse(dto.getEndDate()));
         }
+        receiptInfo.setOperator(dto.getOperator());
         receiptInfo.setCreateTime(LocalDateTime.now());
         receiptInfo.setUpdateTime(LocalDateTime.now());
         aReceiptInfoService.save(receiptInfo);
@@ -178,6 +179,8 @@ public class AContractInfoServiceImpl extends ServiceImpl<AContractInfoMapper, A
             throw new RuntimeException("数据不存在");
         }
         CanBeGetReceiptVo vo = new CanBeGetReceiptVo();
+        vo.setLd(houseInfo.getBuilding());
+        vo.setLc(houseInfo.getFloor());
         vo.setJkdw(houseInfo.getHouseName());
         vo.setZj(houseInfo.getRentRange());
         vo.setYj(contractInfo.getContractDeposit());
@@ -195,6 +198,8 @@ public class AContractInfoServiceImpl extends ServiceImpl<AContractInfoMapper, A
             throw new RuntimeException("数据不存在");
         }
         return new CanBeGetReturnReceiptVo(
+                houseInfo.getBuilding(),
+                houseInfo.getFloor(),
                 houseInfo.getHouseName(),
                 contractInfo.getContractDeposit()
         );

+ 137 - 2
src/main/java/com/zksy/property/service/impl/AReceiptInfoServiceImpl.java

@@ -1,10 +1,13 @@
 package com.zksy.property.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zksy.property.domain.AReceiptInfo;
+import com.zksy.property.domain.vo.AReceiptInfoReportDayVo;
+import com.zksy.property.domain.vo.AReceiptInfoReportVo;
 import com.zksy.property.domain.vo.AReceiptInfoVo;
 import com.zksy.property.mapper.AReceiptInfoMapper;
 import com.zksy.property.service.AReceiptInfoService;
@@ -13,8 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
-import java.util.stream.Collectors;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.*;
@@ -149,6 +150,140 @@ public class AReceiptInfoServiceImpl extends ServiceImpl<AReceiptInfoMapper, ARe
                 .sorted()
                 .collect(Collectors.toList());
     }
+
+    @Override
+    public List<AReceiptInfoReportVo> getReceiptReport(Integer year, Integer month) {
+        List<AReceiptInfoReportVo> resultList = new ArrayList<>();
+        // 按年查询(仅传年份)
+        if (month == null) {
+            resultList.add(sumByYear(year));
+        } else {
+            resultList = sumByMonth(year);
+        }
+        return resultList;
+    }
+
+    @Override
+    public List<AReceiptInfoReportVo> statReceiptDetailByYear(Integer year,String assetType) {
+        return baseMapper.statReceiptByYear(year,assetType);
+    }
+
+    @Override
+    public List<AReceiptInfoReportVo> statReceiptDetailByMonth(Integer year, Integer month,String assetType) {
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("月份必须在1-12之间");
+        }
+        return baseMapper.statReceiptByMonth(year, month,assetType);
+    }
+    @Override
+    public List<AReceiptInfoReportDayVo> statReceiptDetailByDay(Integer year, Integer month,String assetType) {
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("月份必须在1-12之间");
+        }
+        return baseMapper.statReceiptByDay(year, month,assetType);
+    }
+
+    /**
+     * 按年汇总收据数据
+     */
+    private AReceiptInfoReportVo sumByYear(Integer year) {
+        if (year == null) {
+            throw new IllegalArgumentException("年份参数不能为空");
+        }
+        //  构建查询条件
+        QueryWrapper<AReceiptInfo> wrapper = new QueryWrapper<>();
+        // 筛选指定年份的入账日期
+        wrapper.apply("EXTRACT(YEAR FROM accounting_date) = {0}", year)
+                // 指定聚合查询字段,COALESCE确保无数据时返回0
+                .select(
+                        "DATE_FORMAT(accounting_date, '%Y') as receiptTime",
+                        "COALESCE(SUM(rent), 0) as rent",
+                        "COALESCE(SUM(deposit), 0) as deposit",
+                        "COALESCE(SUM(property_fee), 0) as propertyFee",
+                        "COALESCE(SUM(water_fee), 0) as waterFee",
+                        "COALESCE(SUM(electricity_bill), 0) as electricityBill"
+                )
+                // 按年份分组
+                .groupBy("DATE_FORMAT(accounting_date, '%Y')");
+
+        // 执行查询,返回Map结果(MP自动映射字段名)
+        List<Map<String, Object>> resultList = baseMapper.selectMaps(wrapper);
+
+        // 转换为VO(处理无数据情况)
+        AReceiptInfoReportVo yearVo = new AReceiptInfoReportVo();
+        if (CollectionUtil.isNotEmpty(resultList)) {
+            Map<String, Object> dataMap = resultList.get(0);
+            yearVo.setReceiptTime((String) dataMap.get("receiptTime"));
+            yearVo.setRent((BigDecimal) dataMap.get("rent"));
+            yearVo.setDeposit((BigDecimal) dataMap.get("deposit"));
+            yearVo.setPropertyFee((BigDecimal) dataMap.get("propertyFee"));
+            yearVo.setWaterFee((BigDecimal) dataMap.get("waterFee"));
+            yearVo.setElectricityBill((BigDecimal) dataMap.get("electricityBill"));
+        } else {
+            // 无数据时默认值
+            yearVo.setReceiptTime(year.toString());
+            yearVo.setRent(BigDecimal.ZERO);
+            yearVo.setDeposit(BigDecimal.ZERO);
+            yearVo.setPropertyFee(BigDecimal.ZERO);
+            yearVo.setWaterFee(BigDecimal.ZERO);
+            yearVo.setElectricityBill(BigDecimal.ZERO);
+        }
+        return yearVo;
+    }
+
+    /**
+     * 按月汇总指定年份数据
+     */
+    private List<AReceiptInfoReportVo> sumByMonth(Integer year) {
+        // 构建查询条件
+        QueryWrapper<AReceiptInfo> wrapper = new QueryWrapper<>();
+        wrapper.apply("EXTRACT(YEAR FROM accounting_date) = {0}", year)
+                .select(
+                        "DATE_FORMAT(accounting_date, '%Y-%m') as receiptTime",
+                        "EXTRACT(MONTH FROM accounting_date) as month",
+                        "COALESCE(SUM(rent), 0) as rent",
+                        "COALESCE(SUM(deposit), 0) as deposit",
+                        "COALESCE(SUM(property_fee), 0) as propertyFee",
+                        "COALESCE(SUM(water_fee), 0) as waterFee",
+                        "COALESCE(SUM(electricity_bill), 0) as electricityBill"
+                )
+                .groupBy("DATE_FORMAT(accounting_date, '%Y-%m')", "EXTRACT(MONTH FROM accounting_date)");
+
+        // 执行查询
+        List<Map<String, Object>> monthDataList = baseMapper.selectMaps(wrapper);
+
+        // 构建月份数据映射
+        Map<Integer, AReceiptInfoReportVo> monthDataMap = new HashMap<>();
+        if (!CollectionUtil.isEmpty(monthDataList)) {
+            for (Map<String, Object> data : monthDataList) {
+                Integer month = ((Number) data.get("month")).intValue();
+                AReceiptInfoReportVo vo = new AReceiptInfoReportVo();
+                vo.setReceiptTime((String) data.get("receiptTime"));
+                vo.setRent((BigDecimal) data.get("rent"));
+                vo.setDeposit((BigDecimal) data.get("deposit"));
+                vo.setPropertyFee((BigDecimal) data.get("propertyFee"));
+                vo.setWaterFee((BigDecimal) data.get("waterFee"));
+                vo.setElectricityBill((BigDecimal) data.get("electricityBill"));
+                monthDataMap.put(month, vo);
+            }
+        }
+
+        // 生成12个月完整数据
+        List<AReceiptInfoReportVo> resultList = new ArrayList<>();
+        for (int i = 1; i <= 12; i++) {
+            AReceiptInfoReportVo monthVo = monthDataMap.getOrDefault(i, new AReceiptInfoReportVo());
+            if (monthVo.getReceiptTime() == null) {
+                monthVo.setReceiptTime(String.format("%d-%02d", year, i));
+                monthVo.setRent(BigDecimal.ZERO);
+                monthVo.setDeposit(BigDecimal.ZERO);
+                monthVo.setPropertyFee(BigDecimal.ZERO);
+                monthVo.setWaterFee(BigDecimal.ZERO);
+                monthVo.setElectricityBill(BigDecimal.ZERO);
+            }
+            resultList.add(monthVo);
+        }
+        return resultList;
+    }
 }
 
 

+ 128 - 2
src/main/java/com/zksy/property/service/impl/ARefundServiceImpl.java

@@ -2,9 +2,12 @@ package com.zksy.property.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zksy.property.domain.ARefund;
+import com.zksy.property.domain.vo.ARefundReportDayVo;
+import com.zksy.property.domain.vo.ARefundReportVo;
 import com.zksy.property.domain.vo.ARefundVo;
 import com.zksy.property.mapper.ARefundMapper;
 import com.zksy.property.service.ARefundService;
@@ -13,8 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
-import java.util.stream.Collectors;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.*;
@@ -149,6 +150,131 @@ public class ARefundServiceImpl extends ServiceImpl<ARefundMapper, ARefund>
         Page<ARefundVo> page = new Page<>(pageNum, pageSize);
         return aRefundMapper.selectRefundWithContractByPage(page, unit, tenant, contractNumber);
     }
+
+    @Override
+    public List<ARefundReportVo> getRefundReport(Integer year, Integer month) {
+        // 校验年份必填
+        if (year == null) {
+            throw new IllegalArgumentException("年份参数不能为空");
+        }
+        List<ARefundReportVo> resultList = new ArrayList<>();
+        // 按年查询(仅传年份)
+        if (month == null) {
+            resultList.add(sumByYear(year));
+        } else {
+            resultList = sumByMonth(year);
+        }
+        return resultList;
+    }
+
+    @Override
+    public List<ARefundReportVo> statRefundDetailByYear(Integer year,String assetType) {
+        return baseMapper.statRefundByYear(year,assetType);
+    }
+
+    @Override
+    public List<ARefundReportVo> statRefundDetailByMonth(Integer year, Integer month,String assetType) {
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("月份必须在1-12之间");
+        }
+        return baseMapper.statRefundByMonth(year, month,assetType);
+    }
+    @Override
+    public List<ARefundReportDayVo> statRefundDetailByDay(Integer year, Integer month,String assetType) {
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("月份必须在1-12之间");
+        }
+        return baseMapper.statRefundByDay(year, month,assetType);
+    }
+
+
+    /**
+     * 按年汇总退款数据(MySQL适配)
+     * @param year 年份(必填)
+     * @return 年度汇总VO
+     */
+    private ARefundReportVo sumByYear(Integer year) {
+        //构建MySQL适配的查询条件
+        QueryWrapper<ARefund> wrapper = new QueryWrapper<>();
+        wrapper.eq("YEAR(generation_date)", year)
+                .select(
+                        "DATE_FORMAT(generation_date, '%Y') as refundTime",
+                        "IFNULL(SUM(deposit), 0) as deposit",
+                        "IFNULL(SUM(rent), 0) as rent",
+                        "IFNULL(SUM(property_fee), 0) as propertyFee"
+                )
+                .groupBy("DATE_FORMAT(generation_date, '%Y')");
+
+        // 执行查询
+        List<Map<String, Object>> resultList = baseMapper.selectMaps(wrapper);
+
+        // 转换为VO
+        ARefundReportVo yearVo = new ARefundReportVo();
+        if (CollectionUtils.isNotEmpty(resultList)) {
+            Map<String, Object> dataMap = resultList.get(0);
+            yearVo.setRefundTime((String) dataMap.get("refundTime"));
+            yearVo.setDeposit((BigDecimal) dataMap.get("deposit"));
+            yearVo.setRent((BigDecimal) dataMap.get("rent"));
+            yearVo.setPropertyFee((BigDecimal) dataMap.get("propertyFee"));
+        } else {
+            // 无数据时默认值
+            yearVo.setRefundTime(year.toString());
+            yearVo.setDeposit(BigDecimal.ZERO);
+            yearVo.setRent(BigDecimal.ZERO);
+            yearVo.setPropertyFee(BigDecimal.ZERO);
+        }
+        return yearVo;
+    }
+
+    /**
+     * 按月汇总退款数据
+     * @param year 年份(必填)
+     * @return 12个月的汇总VO列表
+     */
+    private List<ARefundReportVo> sumByMonth(Integer year) {
+        // 构建MySQL适配的查询条件
+        QueryWrapper<ARefund> wrapper = new QueryWrapper<>();
+        wrapper.eq("YEAR(generation_date)", year)
+                .select(
+                        "DATE_FORMAT(generation_date, '%Y-%m') as refundTime",
+                        "MONTH(generation_date) as month",
+                        "IFNULL(SUM(deposit), 0) as deposit",
+                        "IFNULL(SUM(rent), 0) as rent",
+                        "IFNULL(SUM(property_fee), 0) as propertyFee"
+                )
+                .groupBy("DATE_FORMAT(generation_date, '%Y-%m')", "MONTH(generation_date)");
+
+        //执行查询
+        List<Map<String, Object>> monthDataList = baseMapper.selectMaps(wrapper);
+
+        //构建月份数据映射
+        Map<Integer, ARefundReportVo> monthDataMap = new HashMap<>();
+        if (!CollectionUtils.isEmpty(monthDataList)) {
+            for (Map<String, Object> data : monthDataList) {
+                Integer month = ((Number) data.get("month")).intValue();
+                ARefundReportVo vo = new ARefundReportVo();
+                vo.setRefundTime((String) data.get("refundTime"));
+                vo.setDeposit((BigDecimal) data.get("deposit"));
+                vo.setRent((BigDecimal) data.get("rent"));
+                vo.setPropertyFee((BigDecimal) data.get("propertyFee"));
+                monthDataMap.put(month, vo);
+            }
+        }
+
+        // 生成12个月完整数据
+        List<ARefundReportVo> resultList = new ArrayList<>();
+        for (int i = 1; i <= 12; i++) {
+            ARefundReportVo monthVo = monthDataMap.getOrDefault(i, new ARefundReportVo());
+            if (monthVo.getRefundTime() == null) {
+                monthVo.setRefundTime(String.format("%d-%02d", year, i));
+                monthVo.setDeposit(BigDecimal.ZERO);
+                monthVo.setRent(BigDecimal.ZERO);
+                monthVo.setPropertyFee(BigDecimal.ZERO);
+            }
+            resultList.add(monthVo);
+        }
+        return resultList;
+    }
 }
 
 

+ 1 - 1
src/main/java/com/zksy/property/service/impl/ARentalContractServiceImpl.java

@@ -70,7 +70,7 @@ public class ARentalContractServiceImpl extends ServiceImpl<ARentalContractMappe
         markToFieldCount.put("1", 9);
         markToFieldCount.put("2", 56);
         markToFieldCount.put("3", 27);
-        markToFieldCount.put("4", 15);
+        markToFieldCount.put("4", 16);
         markToFieldCount.put("5", 8);
 
         // 验证标记类型

+ 1 - 1
src/main/resources/application.yml

@@ -20,7 +20,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: dev
+    active: prod
   # 文件上传
   servlet:
     multipart:

+ 118 - 1
src/main/resources/mapper/property/AReceiptInfoMapper.xml

@@ -16,6 +16,7 @@
             <result property="deposit" column="deposit" jdbcType="DECIMAL"/>
             <result property="waterFee" column="water_fee" jdbcType="DECIMAL"/>
             <result property="electricityBill" column="electricity_bill" jdbcType="DECIMAL"/>
+            <result property="operator" column="operator" jdbcType="VARCHAR"/>
             <result property="attachmentUrl" column="attachment_url" jdbcType="VARCHAR"/>
             <result property="receiptReason" column="receipt_reason" jdbcType="VARCHAR"/>
             <result property="generationDate" column="generation_date" javaType="DATE"/>
@@ -38,6 +39,7 @@
         <result property="deposit" column="deposit" jdbcType="DECIMAL"/>
         <result property="waterFee" column="water_fee" jdbcType="DECIMAL"/>
         <result property="electricityBill" column="electricity_bill" jdbcType="DECIMAL"/>
+        <result property="operator" column="operator" jdbcType="VARCHAR"/>
         <result property="attachmentUrl" column="attachment_url" jdbcType="VARCHAR"/>
         <result property="receiptReason" column="receipt_reason" jdbcType="VARCHAR"/>
         <result property="generationDate" column="generation_date" jdbcType="DATE" javaType="java.time.LocalDate"/>
@@ -53,7 +55,7 @@
         id,contract_id,receipt_number,payer,
         payment_method,total_amount,rent,
         property_fee,deposit,water_fee,electricity bill,
-        receipt_reason,attachment_url,accounting_date,
+        receipt_reason,operator,attachment_url,accounting_date,
         generation_date,start_date,end_date,create_time,update_time
     </sql>
     <select id="selectReceiptWithContractByPage" resultMap="VoResultMap">
@@ -70,6 +72,7 @@
         r.water_fee,
         r.electricity_bill,
         r.receipt_reason,
+        r.operator,
         r.attachment_url,
         r.accounting_date,
         r.generation_date,
@@ -96,4 +99,118 @@
         </where>
         ORDER BY r.create_time DESC
     </select>
+    <!-- 按年统计:返回1-12月明细,receiptTime格式为"X月" -->
+    <select id="statReceiptByYear" resultType="com.zksy.property.domain.vo.AReceiptInfoReportVo">
+        SELECT
+            CONCAT(m.month, '月') AS receiptTime,
+            IFNULL(SUM(r.rent), 0) AS rent,
+            IFNULL(SUM(r.deposit), 0) AS deposit,
+            IFNULL(SUM(r.property_fee), 0) AS propertyFee,
+            IFNULL(SUM(r.water_fee), 0) AS waterFee,
+            IFNULL(SUM(r.electricity_bill), 0) AS electricityBill
+        FROM
+            -- 12个月虚拟表,作为统计的时间维度基础
+            (
+                SELECT 1 AS month UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+                UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
+            ) m
+                -- 左连接:仅筛选出「目标资产类型+指定年份」的收款数据,再按月份匹配
+                LEFT JOIN (
+                -- 子查询:先精准筛选出属于传入assetType的收款数据(核心!先筛选,再关联)
+                SELECT
+                    r.rent, r.deposit, r.property_fee, r.water_fee, r.electricity_bill,
+                    r.accounting_date
+                FROM a_receipt_info r
+                         -- 内连接:仅保留有合同的收款数据
+                         INNER JOIN a_contract_info c ON r.contract_id = c.id
+                    -- 内连接:仅保留有房屋信息的合同数据,且房屋类型严格匹配传入的assetType
+                         INNER JOIN a_simplified_house_info sh ON c.simplified_house_id = sh.id AND sh.asset_type = #{assetType}
+                -- 筛选指定年份的收款数据
+                WHERE YEAR(r.accounting_date) = #{year}
+            ) r ON MONTH(r.accounting_date) = m.month
+        -- 按月份分组合计,保证12个月完整
+        GROUP BY m.month
+        ORDER BY m.month
+    </select>
+
+    <!-- 按月统计:返回当月每日明细,receiptTime格式为"yyyy-MM-dd" -->
+    <select id="statReceiptByMonth" resultType="com.zksy.property.domain.vo.AReceiptInfoReportVo">
+        SELECT
+        DATE_FORMAT(d.day_date, '%Y-%m-%d') AS receiptTime,
+        IFNULL(SUM(r.rent), 0) AS rent,
+        IFNULL(SUM(r.deposit), 0) AS deposit,
+        IFNULL(SUM(r.property_fee), 0) AS propertyFee,
+        IFNULL(SUM(r.water_fee), 0) AS waterFee,
+        IFNULL(SUM(r.electricity_bill), 0) AS electricityBill
+        FROM
+        (
+        <!-- 生成指定年月的所有日期,原逻辑保留不变 -->
+        SELECT
+        DATE_ADD(
+        CONCAT(#{year}, '-', #{month}, '-01'),
+        INTERVAL (t.n - 1) DAY
+        ) AS day_date
+        FROM
+        (
+        SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+        UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
+        UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18
+        UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24
+        UNION ALL SELECT 25 UNION ALL SELECT 26 UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30
+        UNION ALL SELECT 31
+        ) t
+        WHERE
+        DATE_ADD(CONCAT(#{year}, '-', #{month}, '-01'), INTERVAL (t.n - 1) DAY)
+        &lt;= LAST_DAY(CONCAT(#{year}, '-', #{month}, '-01'))
+        ) d
+        <!-- 左连接:日期表关联【筛选后的目标收款数据】,保证日期完整 -->
+        LEFT JOIN (
+        <!-- 子查询:先精准筛选【指定年月+指定资产类型】的有效收款数据(核心) -->
+        SELECT
+        r.rent, r.deposit, r.property_fee, r.water_fee, r.electricity_bill,
+        r.accounting_date
+        FROM a_receipt_info r
+        <!-- 内连接:仅保留有合同的收款 -->
+        INNER JOIN a_contract_info c ON r.contract_id = c.id
+        <!-- 内连接:仅保留有房屋+资产类型匹配的合同,动态判断兼容传/不传assetType -->
+        INNER JOIN a_simplified_house_info sh ON c.simplified_house_id = sh.id
+        <if test="assetType != null and assetType != ''">
+            AND sh.asset_type = #{assetType}
+        </if>
+        <!-- 筛选指定年月的收款数据 -->
+        WHERE YEAR(r.accounting_date) = #{year}
+        AND MONTH(r.accounting_date) = #{month}
+        ) r ON DATE(r.accounting_date) = d.day_date
+        GROUP BY d.day_date
+        ORDER BY d.day_date
+    </select>
+    <select id="statReceiptByDay" resultType="com.zksy.property.domain.vo.AReceiptInfoReportDayVo">
+        SELECT
+        r.receipt_number AS receiptCode, -- 收据号
+        r.payer AS payer, -- 付款人
+        DATE_FORMAT(r.accounting_date, '%Y-%m-%d') AS receiptTime, -- 收取时间
+        -- 租金收取时段:拼接开始时间和结束时间
+        CONCAT(DATE_FORMAT(r.start_date, '%Y-%m-%d'), ' ~ ', DATE_FORMAT(r.end_date, '%Y-%m-%d')) AS rentPeriod,
+        r.operator AS operator, -- 经手人/操作人
+        r.payment_method AS payType, -- 支付方式
+        -- 原有金额字段,去掉外层IFNULL(明细行保留原始值,如需置0可保留)
+        r.rent AS rent, -- 房租
+        r.deposit AS deposit, -- 押金
+        r.water_fee AS waterFee, -- 水费
+        r.electricity_bill AS electricityBill, -- 电费
+        r.property_fee AS propertyFee -- 物业管理费
+        FROM a_receipt_info r
+        <!-- 内连接替代左连接:仅保留有合同+有房屋的有效收款,避免无关联的无效明细 -->
+        INNER JOIN a_contract_info c ON r.contract_id = c.id
+        INNER JOIN a_simplified_house_info h ON c.simplified_house_id = h.id
+        WHERE
+        -- 按传入的年份和月份筛选
+        YEAR(r.accounting_date) = #{year}
+        AND MONTH(r.accounting_date) = #{month}
+        <!-- 资产类型筛选:仅匹配指定类型,移除OR h.asset_type IS NULL(彻底排除非目标类型) -->
+        <if test="assetType != null and assetType != ''">
+            AND h.asset_type = #{assetType}
+        </if>
+        ORDER BY r.accounting_date ASC
+    </select>
 </mapper>

+ 109 - 1
src/main/resources/mapper/property/ARefundMapper.xml

@@ -13,6 +13,7 @@
             <result property="rent" column="rent" jdbcType="DECIMAL"/>
             <result property="propertyFee" column="property_fee" jdbcType="DECIMAL"/>
             <result property="totalAmount" column="total_amount" jdbcType="DECIMAL"/>
+            <result property="operator" column="operator" jdbcType="VARCHAR"/>
             <result property="generationDate" column="generation_date" jdbcType="DATE" javaType="java.time.LocalDate"/>
             <result property="attachmentUrl" column="attachment_url" jdbcType="VARCHAR"/>
             <result property="createTime" column="create_time" jdbcType="TIMESTAMP" javaType="java.time.LocalDateTime"/>
@@ -28,6 +29,7 @@
         <result property="rent" column="rent" jdbcType="DECIMAL"/>
         <result property="propertyFee" column="property_fee" jdbcType="DECIMAL"/>
         <result property="totalAmount" column="total_amount" jdbcType="DECIMAL"/>
+        <result property="operator" column="operator" jdbcType="VARCHAR"/>
         <result property="generationDate" column="generation_date" jdbcType="DATE" javaType="java.time.LocalDate"/>
         <result property="attachmentUrl" column="attachment_url" jdbcType="VARCHAR"/>
         <result property="createTime" column="create_time" jdbcType="TIMESTAMP" javaType="java.time.LocalDateTime"/>
@@ -37,7 +39,7 @@
 
     <sql id="Base_Column_List">
         id,contract_id,unit,tenant,
-        deposit,rent,property_fee,
+        deposit,rent,property_fee,operator,
         total_amount,generation_date,attachment_url,
         create_time,update_time
     </sql>
@@ -52,6 +54,7 @@
             r.rent,
             r.property_fee,
             r.total_amount,
+            r.operator,
             r.generation_date,
             r.attachment_url,
             r.create_time,
@@ -72,4 +75,109 @@
         </where>
         ORDER BY r.create_time DESC
     </select>
+    <!-- 按年统计退款明细:返回1-12月数据,refundTime为"X月" -->
+    <select id="statRefundByYear" resultType="com.zksy.property.domain.vo.ARefundReportVo">
+        SELECT
+        CONCAT(m.month, '月') AS refundTime,
+        IFNULL(SUM(r.deposit), 0) AS deposit,
+        IFNULL(SUM(r.rent), 0) AS rent,
+        IFNULL(SUM(r.property_fee), 0) AS propertyFee
+        FROM
+        (
+        SELECT 1 AS month UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+        UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
+        ) m
+        <!-- 左连接筛选后的退款数据,保证12个月完整 -->
+        LEFT JOIN (
+        <!-- 子查询:先精准筛选指定年份+资产类型的有效退款(核心) -->
+        SELECT
+        r.deposit, r.rent, r.property_fee,
+        r.generation_date
+        FROM a_refund r
+        <!-- 内连接:仅保留有合同的退款 -->
+        INNER JOIN a_contract_info c ON r.contract_id = c.id
+        <!-- 内连接:仅保留有房屋的合同,动态筛选资产类型 -->
+        INNER JOIN a_simplified_house_info h ON c.simplified_house_id = h.id
+        <if test="assetType != null and assetType != ''">
+            AND h.asset_type = #{assetType}
+        </if>
+        <!-- 筛选指定年份的退款 -->
+        WHERE YEAR(r.generation_date) = #{year}
+        ) r ON MONTH(r.generation_date) = m.month
+        GROUP BY m.month
+        ORDER BY m.month
+    </select>
+
+    <!-- 按月统计退款明细:返回当月每日数据,refundTime为"yyyy-MM-dd" -->
+    <select id="statRefundByMonth" resultType="com.zksy.property.domain.vo.ARefundReportVo">
+        SELECT
+        DATE_FORMAT(d.day_date, '%Y-%m-%d') AS refundTime,
+        IFNULL(SUM(r.deposit), 0) AS deposit,
+        IFNULL(SUM(r.rent), 0) AS rent,
+        IFNULL(SUM(r.property_fee), 0) AS propertyFee
+        FROM
+        (
+        <!-- 生成指定年月的所有日期,原逻辑保留不变 -->
+        SELECT
+        DATE_ADD(
+        CONCAT(#{year}, '-', #{month}, '-01'),
+        INTERVAL (t.n - 1) DAY
+        ) AS day_date
+        FROM
+        (
+        SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
+        UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
+        UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18
+        UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23 UNION ALL SELECT 24
+        UNION ALL SELECT 25 UNION ALL SELECT 26 UNION ALL SELECT 27 UNION ALL SELECT 28 UNION ALL SELECT 29 UNION ALL SELECT 30
+        UNION ALL SELECT 31
+        ) t
+        WHERE
+        DATE_ADD(CONCAT(#{year}, '-', #{month}, '-01'), INTERVAL (t.n - 1) DAY)
+        &lt;= LAST_DAY(CONCAT(#{year}, '-', #{month}, '-01'))
+        ) d
+        <!-- 左连接筛选后的退款数据,保证当月日期完整 -->
+        LEFT JOIN (
+        <!-- 子查询:先精准筛选指定年月+资产类型的有效退款(核心) -->
+        SELECT
+        r.deposit, r.rent, r.property_fee,
+        r.generation_date
+        FROM a_refund r
+        <!-- 内连接:仅保留有合同的退款 -->
+        INNER JOIN a_contract_info c ON r.contract_id = c.id
+        <!-- 内连接:仅保留有房屋的合同,动态筛选资产类型 -->
+        INNER JOIN a_simplified_house_info h ON c.simplified_house_id = h.id
+        <if test="assetType != null and assetType != ''">
+            AND h.asset_type = #{assetType}
+        </if>
+        <!-- 筛选指定年月的退款 -->
+        WHERE YEAR(r.generation_date) = #{year}
+        AND MONTH(r.generation_date) = #{month}
+        ) r ON DATE(r.generation_date) = d.day_date
+        GROUP BY d.day_date
+        ORDER BY d.day_date
+    </select>
+    <select id="statRefundByDay" resultType="com.zksy.property.domain.vo.ARefundReportDayVo">
+        SELECT
+        DATE_FORMAT(r.generation_date, '%Y-%m-%d') AS refundTime,
+        r.tenant AS tenant, -- 租户
+        r.operator AS operator, -- 经手人
+        IFNULL(r.rent, 0) AS rent, -- 房租退款
+        IFNULL(r.deposit, 0) AS deposit, -- 押金退款
+        IFNULL(r.property_fee, 0) AS propertyFee -- 物业费退款
+        FROM a_refund r
+        <!-- 内连接:仅保留有合同的有效退款 -->
+        INNER JOIN a_contract_info c ON r.contract_id = c.id
+        <!-- 内连接:仅保留有房屋的有效合同,动态筛选资产类型 -->
+        INNER JOIN a_simplified_house_info h ON c.simplified_house_id = h.id
+        WHERE
+        -- 筛选指定年月的退款
+        YEAR(r.generation_date) = #{year}
+        AND MONTH(r.generation_date) = #{month}
+        <!-- 资产类型精准筛选:移除OR h.asset_type IS NULL,避免非目标类型混入 -->
+        <if test="assetType != null and assetType != ''">
+            AND h.asset_type = #{assetType}
+        </if>
+        ORDER BY r.generation_date ASC
+    </select>
 </mapper>

BIN
src/main/resources/templates/1.docx


BIN
src/main/resources/templates/4.docx


+ 2 - 4
src/test/java/com/zksy/property/service/impl/AContractInfoServiceImplTest.java

@@ -1,13 +1,11 @@
 package com.zksy.property.service.impl;
 
 import com.zksy.property.domain.dto.ContractFormDTO;
-import com.zksy.property.domain.dto.ReceiptDto;
 import com.zksy.property.service.AContractInfoService;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
-import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -130,7 +128,7 @@ class AContractInfoServiceImplTest {
         aContractInfoService.signContract(dto);
     }
 
-    @Test
+/*    @Test
     void getReceipt(){
         var dto = new ReceiptDto(
                 "1",
@@ -146,6 +144,6 @@ class AContractInfoServiceImplTest {
         );
         String receipt = aContractInfoService.getReceipt("31c7f3fdfc236328bce3307645d566dd",dto);
         System.out.println(receipt);
-    }
+    }*/
 
 }