ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ScreenController.java
@@ -1,10 +1,12 @@ package com.ruoyi.web.controller.api; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; 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; @@ -31,6 +33,8 @@ import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; import static org.checkerframework.checker.units.qual.Prefix.one; /** * @author mitao @@ -69,20 +73,22 @@ @ApiOperation(value = "租户数量趋势统计") public R<List<TenantCountTrendVO>> getTenantCountTrend() { String businessDeptId = SecurityUtils.getBusinessDeptId(); Date currentDate = new Date(); Date targetDate = DateUtils.addMonths(currentDate, -3 * 6); Map<String, Date> startQuarterDate = DateUtils.getQuarterDate(targetDate); Date targetDate2 = DateUtils.addMonths(currentDate, 0); Map<String, Date> endQuarterDate = DateUtils.getQuarterDate(targetDate2); List<TContract> contracts = contractService.list(new LambdaQueryWrapper<TContract>() .eq(!"0".equals(businessDeptId),TContract::getBusinessDeptId, businessDeptId) .isNotNull(TContract::getSignTime) .between(TContract::getSignTime, startQuarterDate.get("first"), endQuarterDate.get("last")) .orderByAsc(TContract::getSignTime)); // 创建季度格式化工具(示例:2025-Q1) DateTimeFormatter quarterFormatter = DateTimeFormatter.ofPattern("yyyy-'Q'Q"); DateTimeFormatter quarterFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); List<TenantCountTrendVO> trendData = contracts.stream() .collect(Collectors.groupingBy(contract -> { @@ -107,9 +113,14 @@ @ApiOperation("获取实时租赁数据") public R<List<RealTimeRentDataVO>> getRealTimeRentData() { // 随机获取十条房源 String businessDeptId = SecurityUtils.getBusinessDeptId(); List<THouse> houses = houseService.list(new LambdaQueryWrapper<THouse>() .eq(!"0".equals(businessDeptId),THouse::getBusinessDeptId, businessDeptId) .last("ORDER BY RAND() LIMIT 10")); if (CollectionUtil.isEmpty(houses)){ return R.ok(new ArrayList<>()); } // 提取streetIds List<String> streetIds = houses.stream() @@ -124,7 +135,7 @@ List<RealTimeRentDataVO> result = houses.stream().map(house -> { RealTimeRentDataVO vo = new RealTimeRentDataVO(); vo.setStreetName(streetMap.getOrDefault(house.getStreetId(), "未知")); vo.setRoomName(house.getRoomNumber()); vo.setRoomName(house.getHouseName()); vo.setLeaseStatus(house.getLeaseStatus()); return vo; }).collect(Collectors.toList()); @@ -138,8 +149,11 @@ @GetMapping("/getHouseMapDistribution") @ApiOperation("获取房屋地图分布") public R<List<HouseMapDistributionVO>> getHouseMapDistribution() { String businessDeptId = SecurityUtils.getBusinessDeptId(); // 获取所有房屋信息 List<THouse> houses = houseService.list(); List<THouse> houses = houseService.list(new LambdaQueryWrapper<THouse>() .eq(!"0".equals(businessDeptId),THouse::getBusinessDeptId, businessDeptId)); List<HouseMapDistributionVO> result = new ArrayList<>(); for (THouse house : houses) { HouseMapDistributionVO houseMapDistributionVO = new HouseMapDistributionVO(); @@ -149,6 +163,7 @@ houseMapDistributionVO.setLongitude(house.getLongitude()); houseMapDistributionVO.setLatitude(house.getLatitude()); TContract contract = contractService.getOne(new LambdaQueryWrapper<TContract>() .eq(!"0".equals(businessDeptId),TContract::getBusinessDeptId, businessDeptId) .gt(TContract::getEndTime, LocalDate.now()) .eq(TContract::getHouseId, house.getId()) .eq(TContract::getStatus, 4) @@ -156,6 +171,7 @@ if (contract != null){ List<TBill> tBills = billService.list(new LambdaQueryWrapper<TBill>() .eq(!"0".equals(businessDeptId),TBill::getBusinessDeptId, businessDeptId) .eq(TBill::getContractId, contract.getId()) .eq(TBill::getBillType, 1)); houseMapDistributionVO.setTenant(contract.getPartyTwoName()); @@ -174,23 +190,34 @@ houseMapDistributionVO.setRentStatus(rentStatus); TBill one = billService.getOne(new LambdaQueryWrapper<TBill>() // TBill one = billService.getOne(new LambdaQueryWrapper<TBill>() // .le(TBill::getStartTime, LocalDate.now()) // .ge(TBill::getEndTime, LocalDate.now()) // .eq(TBill::getBillType, 1) // .eq(TBill::getContractId, contract.getId())); List<TBill> ones = billService.list(new LambdaQueryWrapper<TBill>() .eq(!"0".equals(businessDeptId),TBill::getBusinessDeptId, businessDeptId) .le(TBill::getStartTime, LocalDate.now()) .ge(TBill::getEndTime, LocalDate.now()) .eq(TBill::getBillType, 1) .eq(TBill::getContractId, contract.getId())); if ("4".equals(one.getPayFeesStatus())){ houseMapDistributionVO.setHouseStatus("4"); TBill one = null; if (!ones.isEmpty()){ one = ones.get(0); } BigDecimal payFeesMoney = one.getPayFeesMoney(); BigDecimal payableFeesMoney1 = one.getPayableFeesMoney(); String rent = String.format("%.2f/%.2f", payFeesMoney, payableFeesMoney1); houseMapDistributionVO.setRent(rent); if (one != null){ if ("4".equals(one.getPayFeesStatus())){ houseMapDistributionVO.setHouseStatus("4"); } BigDecimal payFeesMoney = one.getPayFeesMoney(); BigDecimal payableFeesMoney1 = one.getPayableFeesMoney(); String rent = String.format("%.2f/%.2f", payFeesMoney, payableFeesMoney1); houseMapDistributionVO.setRent(rent); }else { houseMapDistributionVO.setRent("暂无"); } }else { houseMapDistributionVO.setTenant("暂无"); houseMapDistributionVO.setRentStatus("暂无"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -26,10 +26,21 @@ import com.ruoyi.system.dto.TContractDTO; import com.ruoyi.system.dto.TerminateContractDTO; import com.ruoyi.system.export.ContractExport; import com.ruoyi.system.model.*; import com.ruoyi.system.model.TBill; import com.ruoyi.system.model.TCheckAcceptRecord; import com.ruoyi.system.model.TContract; import com.ruoyi.system.model.TContractRentType; import com.ruoyi.system.model.THouse; import com.ruoyi.system.model.TTenant; import com.ruoyi.system.query.TContractBillQuery; import com.ruoyi.system.query.TContractQuery; import com.ruoyi.system.service.*; import com.ruoyi.system.service.StateProcessTemplateService; import com.ruoyi.system.service.TBillService; import com.ruoyi.system.service.TCheckAcceptRecordService; import com.ruoyi.system.service.TContractRentTypeService; import com.ruoyi.system.service.TContractService; import com.ruoyi.system.service.THouseService; import com.ruoyi.system.service.TTenantService; import com.ruoyi.system.task.base.QuartzManager; import com.ruoyi.system.task.base.TimeJobType; import com.ruoyi.system.task.jobs.StateProcessJob; @@ -45,7 +56,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; @@ -56,7 +73,14 @@ import java.net.URLEncoder; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; /** * <p> @@ -500,7 +524,7 @@ if (StringUtils.isEmpty(key)){ throw new RuntimeException("key不能为空"); } templateParam.put(StringUtils.format("${{}}", "contractNumber"), value != null ? value : ""); templateParam.put("${"+key+"}", value != null ? value : ""); } /** @@ -560,7 +584,33 @@ e.printStackTrace(); } } @ApiOperation("上传合同附件") @PostMapping(value = "/upload-file") public R<Boolean> uploadFile(@RequestBody TContractDTO dto ) { if (Objects.isNull(dto.getId())) { throw new ServiceException("合同id不能为空"); } TContract contract = contractService.getById(dto.getId()); if (Objects.isNull(contract)) { throw new ServiceException("合同不存在"); } if (StringUtils.isNotBlank(contract.getContractFile())) { List<String> contractFileList = Arrays.stream(contract.getContractFile().split(",")).collect(Collectors.toList()); List<String> memoryList = Arrays.stream(contract.getMemory().split(",")).collect(Collectors.toList()); List<String> contractNameList = Arrays.stream(contract.getContractFileName().split(",")).collect(Collectors.toList()); contractFileList.addAll(Arrays.asList(dto.getContractFile().split(","))); contractNameList.addAll(Arrays.asList(dto.getContractFileName().split(","))); memoryList.addAll(Arrays.asList(dto.getMemory().split(","))); contract.setContractFile(String.join(",", contractFileList)); contract.setContractFileName(String.join(",", contractNameList)); contract.setMemory(String.join(",", memoryList)); } else { contract.setContractFile(dto.getContractFile()); contract.setContractFileName(dto.getContractFileName()); contract.setMemory(dto.getMemory()); } return R.ok(contractService.updateById(contract)); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
@@ -5,18 +5,31 @@ import freemarker.template.Template; import freemarker.template.TemplateException; import lombok.extern.slf4j.Slf4j; import org.apache.poi.xwpf.usermodel.*; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.*; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; ruoyi-applet/src/main/resources/application.yml
@@ -1,4 +1,4 @@ # 项目相关配置 spring: profiles: active: prod active: test ruoyi-system/src/main/java/com/ruoyi/system/dto/TerminateContractDTO.java
@@ -1,5 +1,6 @@ package com.ruoyi.system.dto; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -20,6 +21,7 @@ @ApiModelProperty(value = "终止日期") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime terminateTime; } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillMapper.java
@@ -50,5 +50,5 @@ * 街道租金排行 * @return */ List<ScreenRentRankVO> getStreetRentRank(); List<ScreenRentRankVO> getStreetRentRank(@Param("businessDeptId") String businessDeptId); } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TContractMapper.java
@@ -32,5 +32,5 @@ * 本月新增租户数 * @return */ Integer getCurrentMonthRentCount(); Integer getCurrentMonthRentCount(@Param("businessDeptId") String businessDeptId); } ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
@@ -11,7 +11,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.NotBlank; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -126,7 +125,6 @@ @ApiModelProperty(value = "合同附件,多个逗号拼接") @TableField("contract_file") @NotBlank(message = "合同附件不能为空") private String contractFile; @ApiModelProperty(value = "备注") ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
@@ -95,5 +95,5 @@ * 查询街道租金排行 * @return */ List<ScreenRentRankVO> getStreetRentRank(); List<ScreenRentRankVO> getStreetRentRank(String businessDeptId); } ruoyi-system/src/main/java/com/ruoyi/system/service/TContractService.java
@@ -47,5 +47,5 @@ * 本月新增租户数 * @return */ Integer getCurrentMonthRentCount(); Integer getCurrentMonthRentCount(String businessDeptId); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ScreenService.java
@@ -1,6 +1,8 @@ package com.ruoyi.system.service.impl; import com.ruoyi.common.enums.BillTypeEnum; 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; @@ -16,7 +18,12 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; 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 @@ -33,9 +40,12 @@ * @return */ public ScreenTopStaticsDataVO getTopStaticsData() { String businessDeptId = SecurityUtils.getBusinessDeptId(); ScreenTopStaticsDataVO vo = new ScreenTopStaticsDataVO(); //房屋总面积 List<THouse> houseList = tHouseService.list(); List<THouse> 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); @@ -47,7 +57,10 @@ .reduce(0D, Double::sum); vo.setHouseRentedArea(totalRentedArea); //总计应收租金 List<TBill> billList = tBillService.list(); List<TBill> billList = tBillService.lambdaQuery() .eq(!businessDeptId.equals("0"), TBill::getBusinessDeptId, businessDeptId) .eq(TBill::getBillType, BillTypeEnum.Zujin.getCode()) .list(); BigDecimal totalReceivableRent = billList.stream() .filter(item -> !item.getPayFeesStatus().equals("5")) .map(TBill::getPayableFeesMoney) @@ -61,11 +74,12 @@ .divide(new BigDecimal("10000"),2, RoundingMode.HALF_UP); vo.setTotalReceivedRent(totalReceivedRent); //本月新增租户数 Integer newTenantCount = tContractService.getCurrentMonthRentCount(); Integer newTenantCount = tContractService.getCurrentMonthRentCount(businessDeptId); vo.setNewTenantCount(newTenantCount); //总计租户数 系统租户列表里有生效合同绑定的租户总数。 List<TContract> tContracts = tContractService.lambdaQuery() .in(TContract::getStatus, "4", "5", "6", "7", "8", "9") .eq(!businessDeptId.equals("0"), TContract::getBusinessDeptId, businessDeptId) .list(); long count = tContracts.stream() .map(TContract::getTenantId) @@ -76,7 +90,10 @@ Date first = quarterDate.get("first"); Date last = quarterDate.get("last"); List<TBill> currentQuarterBillList = tBillService.lambdaQuery() .eq(!businessDeptId.equals("0"), TBill::getBusinessDeptId, businessDeptId) .between(TBill::getPayableFeesTime, first, last) .eq(TBill::getBillType, BillTypeEnum.Zujin.getCode()) .ne(TBill::getPayFeesStatus, 5) .list(); //本季度已交租金 BigDecimal totalRentPaid = currentQuarterBillList.stream() @@ -98,7 +115,11 @@ .divide(BigDecimal.valueOf(10000L), 2, RoundingMode.HALF_UP); vo.setTotalRentOwe(totalRentOwe); //总计欠费 List<TBill> allBillList = tBillService.lambdaQuery().le(TBill::getPayableFeesTime, last).list(); List<TBill> allBillList = tBillService.lambdaQuery() .eq(TBill::getBillType, BillTypeEnum.Zujin.getCode()) .eq(!businessDeptId.equals("0"), TBill::getBusinessDeptId, businessDeptId) //.le(TBill::getPayableFeesTime, last) .list(); BigDecimal totalRentOweAll = allBillList.stream() .map(TBill::getOutstandingMoney) .reduce(BigDecimal.ZERO, BigDecimal::add) @@ -112,7 +133,8 @@ * @return */ public List<ScreenRentRankVO> streetRentRank() { return tBillService.getStreetRentRank(); String businessDeptId = SecurityUtils.getBusinessDeptId(); return tBillService.getStreetRentRank(businessDeptId); } /** @@ -121,7 +143,7 @@ */ public ScreenRentIncomeTrendVO rentIncomeTrend() { ScreenRentIncomeTrendVO vo = new ScreenRentIncomeTrendVO(); String businessDeptId = SecurityUtils.getBusinessDeptId(); // 获取当前日期 Date currentDate = new Date(); List<String> quarterLabels = new ArrayList<>(); // 季度标签列表 @@ -139,6 +161,8 @@ // 获取该季度的账单数据 List<TBill> quarterBills = tBillService.lambdaQuery() .between(TBill::getPayableFeesTime, quarterStart, quarterEnd) .eq(TBill::getBillType, BillTypeEnum.Zujin.getCode()) .eq(!businessDeptId.equals("0"), TBill::getBusinessDeptId, businessDeptId) .list(); // 计算季度租金收入总和 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -585,7 +585,7 @@ * @return */ @Override public List<ScreenRentRankVO> getStreetRentRank() { return baseMapper.getStreetRentRank(); public List<ScreenRentRankVO> getStreetRentRank(String businessDeptId) { return baseMapper.getStreetRentRank(businessDeptId); } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
@@ -211,7 +211,7 @@ * @return */ @Override public Integer getCurrentMonthRentCount() { return baseMapper.getCurrentMonthRentCount(); public Integer getCurrentMonthRentCount(String businessDeptId) { return baseMapper.getCurrentMonthRentCount(businessDeptId); } } ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
@@ -204,6 +204,11 @@ LEFT JOIN t_house th ON ts.id = th.street_id LEFT JOIN t_contract tc ON tc.house_id = th.id LEFT JOIN t_bill tb ON tc.id = tb.contract_id <where> <if test="businessDeptId != 0"> AND th.business_dept_id = #{businessDeptId} </if> </where> GROUP BY ts.id ORDER BY rentAmount DESC </select> ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml
@@ -130,16 +130,21 @@ <select id="getCurrentMonthRentCount" resultType="java.lang.Integer"> SELECT COUNT(DISTINCT tc.tenant_id) AS new_tenant_count FROM t_contract tc WHERE -- 筛选本月签订的合同 DATE_FORMAT(tc.sign_time, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m') AND tc.status IN ("4", "5", "6", "7", "8", "9") -- 且租户在本月前从未签订过任何合同 AND NOT EXISTS ( SELECT 1 FROM t_contract tc_hist WHERE tc_hist.tenant_id = tc.tenant_id AND tc_hist.sign_time <![CDATA[ < ]]> DATE_FORMAT(CURDATE(), '%Y-%m-01') AND tc_hist.status IN ("4", "5", "6", "7", "8", "9") ) <where> <if test="businessDeptId!=0"> AND tc.business_dept_id = #{businessDeptId} </if> -- 筛选本月签订的合同 AND DATE_FORMAT(tc.sign_time, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m') AND tc.status IN ("4", "5", "6", "7", "8", "9") -- 且租户在本月前从未签订过任何合同 AND NOT EXISTS ( SELECT 1 FROM t_contract tc_hist WHERE tc_hist.tenant_id = tc.tenant_id AND tc_hist.sign_time <![CDATA[ < ]]> DATE_FORMAT(CURDATE(), '%Y-%m-01') AND tc_hist.status IN ("4", "5", "6", "7", "8", "9") ) </where> </select> </mapper>