package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.system.model.TBill; import com.ruoyi.system.model.TContract; import com.ruoyi.system.model.THouse; import com.ruoyi.system.service.TBillService; import com.ruoyi.system.service.TContractService; import com.ruoyi.system.service.THouseService; import com.ruoyi.system.vo.ScreenRentIncomeTrendVO; import com.ruoyi.system.vo.ScreenRentRankVO; import com.ruoyi.system.vo.ScreenTopStaticsDataVO; import com.ruoyi.system.vo.TenantCountTrendVO; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; /** * @author mitao * @date 2025/3/19 */ @Service @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class ScreenService { private final THouseService tHouseService; private final TContractService tContractService; private final TBillService tBillService; private final TContractService contractService; /** * 获取顶部统计数据 * @return */ public ScreenTopStaticsDataVO getTopStaticsData() { String businessDeptId = SecurityUtils.getBusinessDeptId(); Map quarterDate = DateUtils.getQuarterDate(new Date()); Date first = quarterDate.get("first"); Date last = quarterDate.get("last"); ScreenTopStaticsDataVO vo = new ScreenTopStaticsDataVO(); //房屋总面积 List houseList = tHouseService.lambdaQuery() .eq(!businessDeptId.equals("0"), THouse::getBusinessDeptId, businessDeptId) .list(); Double totalArea = houseList.stream() .map(item -> Double.parseDouble(item.getHouseArea())) .reduce(0D, Double::sum); vo.setHouseTotalArea(totalArea); //已出租面积 Double totalRentedArea = tHouseService.getRentedArea(businessDeptId); vo.setHouseRentedArea(totalRentedArea); //总计应收租金 List billList = tBillService.getJiFuBillList(businessDeptId); BigDecimal totalReceivableRent = billList.stream() .filter(item -> !item.getPayFeesStatus().equals("5")) .map(TBill::getPayableFeesMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(new BigDecimal("10000"),2, RoundingMode.DOWN); vo.setTotalReceivableRent(totalReceivableRent); //总计已收租金 BigDecimal totalReceivedRent = billList.stream() .map(TBill::getPayFeesMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(new BigDecimal("10000"),2, RoundingMode.DOWN); vo.setTotalReceivedRent(totalReceivedRent); //本月新增租户数 Integer newTenantCount = tContractService.getCurrentMonthRentCount(businessDeptId); vo.setNewTenantCount(newTenantCount); //总计租户数 系统租户列表里有生效合同绑定的租户总数。 List tContracts = tContractService.lambdaQuery() .eq(TContract::getPayType,2) //季付 .in(TContract::getStatus, "4", "5", "6", "7", "8", "9") .eq(!businessDeptId.equals("0"), TContract::getBusinessDeptId, businessDeptId) .list(); long count = tContracts.stream() .map(TContract::getTenantId) .distinct() .count(); vo.setTotalTenantCount((int) count); List currentQuarterBillList = tBillService.getJiFuBillListByTime(businessDeptId, first, last); //本季度已交租金 BigDecimal totalRentPaid = currentQuarterBillList.stream() .map(TBill::getPayFeesMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(new BigDecimal("10000"),2, RoundingMode.DOWN); vo.setTotalRentPaid(totalRentPaid); //本季度应交租金 BigDecimal totalRentShould = currentQuarterBillList.stream() .filter(item -> !item.getPayFeesStatus().equals("5")) .map(TBill::getPayableFeesMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(new BigDecimal("10000"),2, RoundingMode.DOWN); vo.setTotalRentShould(totalRentShould); //本季度欠费 BigDecimal totalRentOwe = currentQuarterBillList.stream() .map(TBill::getOutstandingMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN); vo.setTotalRentOwe(totalRentOwe); //总计欠费 BigDecimal totalRentOweAll = billList.stream() .map(TBill::getOutstandingMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN); vo.setTotalRentOweAll(totalRentOweAll); return vo; } /** * 区域租金排名 * @return */ public List streetRentRank() { String businessDeptId = SecurityUtils.getBusinessDeptId(); return tBillService.getStreetRentRank(businessDeptId); } /** * 租金收入趋势 * @return */ public ScreenRentIncomeTrendVO rentIncomeTrend() { ScreenRentIncomeTrendVO vo = new ScreenRentIncomeTrendVO(); String businessDeptId = SecurityUtils.getBusinessDeptId(); // 获取当前日期 Date currentDate = new Date(); List quarterLabels = new ArrayList<>(); // 季度标签列表 List incomeData = new ArrayList<>(); //收入数据列表 List outstandingData = new ArrayList<>(); // 欠费数据列表 // 获取最近7个季度的数据 for (int i = 6; i >= 0; i--) { // 计算对应季度的起止时间 Date targetDate = DateUtils.addMonths(currentDate, -3 * i); Map quarterDate = DateUtils.getQuarterDate(targetDate); Date quarterStart = quarterDate.get("first"); Date quarterEnd = quarterDate.get("last"); // 获取该季度的账单数据 List quarterBills = tBillService.getJiFuBillListByTime(businessDeptId, quarterStart, quarterEnd); // 计算季度租金收入总和 BigDecimal quarterIncome = quarterBills.stream() .map(TBill::getPayFeesMoney) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN); // 计算季度欠费总和 BigDecimal quarterOutstanding = quarterBills.stream() .map(TBill::getOutstandingMoney) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.DOWN); // 生成季度标签 (格式: YY-MM月) Calendar cal = Calendar.getInstance(); cal.setTime(quarterEnd); String label = String.format("%02d-%d月", cal.get(Calendar.YEAR) % 100, cal.get(Calendar.MONTH) + 1); quarterLabels.add(label); incomeData.add(quarterIncome); outstandingData.add(quarterOutstanding); // 添加欠费数据 } vo.setQuarters(quarterLabels); vo.setIncomeData(incomeData); vo.setOutstandingData(outstandingData); // 设置欠费数据到VO return vo; } public R> getTenantCountTrend() { // 获取当前日期 Date currentDate = new Date(); String businessDeptId = SecurityUtils.getBusinessDeptId(); List list = new ArrayList<>(); for (int i = 6; i >= 0; i--) { Date targetDate = DateUtils.addMonths(currentDate, -3 * i); Map quarterDate = DateUtils.getQuarterDate(targetDate); Date quarterStart = quarterDate.get("first"); Date quarterEnd = quarterDate.get("last"); System.out.println("第" + (i + 1) + "季度的起止时间:" + quarterStart + " - " + quarterEnd); List contracts = contractService.list(new LambdaQueryWrapper() .eq(!"0".equals(businessDeptId), TContract::getBusinessDeptId, businessDeptId) .eq(TContract::getPayType, 2) .isNotNull(TContract::getSignTime) .between(TContract::getSignTime, quarterStart, quarterEnd) .orderByAsc(TContract::getSignTime)); TenantCountTrendVO vo = new TenantCountTrendVO(); // 生成季度标签 (格式: YY-MM月) Calendar cal = Calendar.getInstance(); cal.setTime(quarterEnd); String label = String.format("%02d-%d月", cal.get(Calendar.YEAR) % 100, cal.get(Calendar.MONTH) + 1); vo.setDate(label); long count = contracts.stream().map(TContract::getTenantId).distinct().count(); vo.setCount(count); list.add(vo); } return R.ok(list); } // // // // // // // // DateTimeFormatter quarterFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // // List trendData = contracts.stream() // .collect(Collectors.groupingBy(contract -> { // LocalDate date = contract.getSignTime().toLocalDate(); // int quarter = (date.getMonthValue() - 1) / 3 + 1; // return YearQuarter.from(date.withMonth(quarter * 3 - 2)); // }, TreeMap::new, Collectors.counting())) // .entrySet().stream() // .map(entry -> new TenantCountTrendVO( // entry.getKey().format(quarterFormatter), // entry.getValue())) // .collect(Collectors.toList()); // // return R.ok(trendData); // } }