zhangmei
2025-02-11 2ba52666860b04bedff1da95af0f6445315e6128
Merge branch 'xizang-changyun' of https://gitee.com/xiaochen991015/xizang into xizang-changyun

# Conflicts:
# ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInvoiceToBillMapper.java
# ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoiceToBill.java
# ruoyi-system/src/main/java/com/ruoyi/system/service/TInvoiceToBillService.java
# ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java
13个文件已删除
23个文件已修改
19个文件已添加
1262 ■■■■■ 已修改文件
generator/src/main/java/com/ruoyi/system/controller/TOrderBillController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/controller/TPayOrderController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/mapper/TOrderBillMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/mapper/TPayOrderMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/model/TOrderBill.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/model/TPayOrder.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/service/TOrderBillService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/service/TPayOrderService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/service/impl/TOrderBillServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/service/impl/TPayOrderServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/resources/mapping/TBankFlowMapper.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/resources/mapping/TOrderBillMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/resources/mapping/TPayOrderMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/test/java/com/xizang/CodeGeneratorTests.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillConfirmController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillDetailController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/THouseController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/PayController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillConfirmController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/OfflinePayDto.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TInvoiceDTO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillConfirmMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillDetailMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInvoiceToBillMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBillConfirm.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TBillDetail.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoiceToBill.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillConfirmService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillDetailService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeptService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TInvoiceToBillService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillConfirmServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillDetailServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeptServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBillConfirmMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBillDetailMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TInvoiceToBillMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generator/src/main/java/com/ruoyi/system/controller/TOrderBillController.java
File was deleted
generator/src/main/java/com/ruoyi/system/controller/TPayOrderController.java
File was deleted
generator/src/main/java/com/ruoyi/system/mapper/TOrderBillMapper.java
File was deleted
generator/src/main/java/com/ruoyi/system/mapper/TPayOrderMapper.java
File was deleted
generator/src/main/java/com/ruoyi/system/model/TOrderBill.java
File was deleted
generator/src/main/java/com/ruoyi/system/model/TPayOrder.java
File was deleted
generator/src/main/java/com/ruoyi/system/service/TOrderBillService.java
File was deleted
generator/src/main/java/com/ruoyi/system/service/TPayOrderService.java
File was deleted
generator/src/main/java/com/ruoyi/system/service/impl/TOrderBillServiceImpl.java
File was deleted
generator/src/main/java/com/ruoyi/system/service/impl/TPayOrderServiceImpl.java
File was deleted
generator/src/main/resources/mapping/TBankFlowMapper.xml
File was deleted
generator/src/main/resources/mapping/TOrderBillMapper.xml
File was deleted
generator/src/main/resources/mapping/TPayOrderMapper.xml
File was deleted
generator/src/test/java/com/xizang/CodeGeneratorTests.java
@@ -35,7 +35,7 @@
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = "D:\\畅云\\项目\\xizangweb\\xizang\\generator";
        String projectPath = "F:\\workSpace\\xizang\\generator";
        gc.setOutputDir(projectPath + "/src/main/java")
                .setAuthor("xiaochen")
                .setMapperName("%sMapper")
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillConfirmController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 账单线下缴费关联表 前端控制器
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@RestController
@RequestMapping("/t-bill-confirm")
public class TBillConfirmController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -3,11 +3,14 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.dto.TbillSaveDto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.service.TBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -34,6 +37,14 @@
        return R.ok(pageInfo);
    }
    @PostMapping("add")
    public R<PageInfo<TBillDto>> add(@Validated @RequestBody TbillSaveDto bill){
        tBillService.saveBill(bill);
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillDetailController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 账单水电费子表 前端控制器
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@RestController
@RequestMapping("/t-bill-detail")
public class TBillDetailController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -37,6 +37,7 @@
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
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.*;
@@ -72,12 +73,15 @@
    private TCheckAcceptRecordService checkAcceptRecordService;
    @ApiOperation(value = "获取合同分页列表")
    @PostMapping(value = "/contractList")
    @PreAuthorize("@ss.hasPermi('system:contract:list')")
    public R<PageInfo<TContract>> contractList(@RequestBody TContractQuery query) {
        return R.ok(contractService.contractList(query));
    }
    @Log(title = "合同管理-新增合同", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增合同")
    @PostMapping(value = "/addContract")
    @PreAuthorize("@ss.hasPermi('system:contract:add')")
    public R<Boolean> addContract(@Validated @RequestBody TContractDTO dto) {
        contractService.save(dto);
        if (dto.getIsIncreasing()){
@@ -210,17 +214,13 @@
        String url = wordUtil.generatePdf("/templates", "1_yzj_租赁合同.xml", templateParam, "租赁合同", "E:\\");
        return R.ok(url);
    }
    @ApiOperation(value = "导出")
    @PostMapping("/export")
    public void export(@RequestBody TContractQuery query){
        contractService.export(query);
    }
    /**
     * 光缆巡检列表导出
     */
    @ApiOperation(value = "光缆巡检列表导出")
    @Log(title = "现场作业-光缆巡检列表导出", businessType = BusinessType.EXPORT)
    @PostMapping("/exportOpticalInspection")
    @ApiOperation(value = "导出")
    @Log(title = "导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void exportOpticalInspection(@RequestBody TContractQuery query)
    {
        List<ContractExport> contractExports = new ArrayList<>();
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeptController.java
@@ -6,7 +6,6 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.dto.TDeptUpAndDownDTO;
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/THouseController.java
@@ -22,6 +22,7 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -45,18 +46,21 @@
    @Log(title = "房屋基础信息管理-新增房屋", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增房屋")
    @PostMapping(value = "/addHouse")
    @PreAuthorize("@ss.hasPermi('system:house:add')")
    public R<Boolean> addHouse(@Validated @RequestBody THouseDTO dto) {
        return R.ok(tHouseService.save(dto));
    }
    @Log(title = "房屋基础信息管理-编辑房屋", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "编辑房屋")
    @PostMapping(value = "/updateHouse")
    @PreAuthorize("@ss.hasPermi('system:house:edit')")
    public R<Boolean> updateHouse(@Validated @RequestBody THouseDTO dto) {
        return R.ok(tHouseService.updateById(dto));
    }
    @Log(title = "房屋基础信息管理-查询房屋信息", businessType = BusinessType.DELETE)
    @ApiOperation(value = "查询房屋信息")
    @GetMapping(value = "/getHouseById")
    @PreAuthorize("@ss.hasPermi('system:house:detail')")
    public R<THouse> getHouseById(@RequestParam String id) {
        THouse tHouse = tHouseService.getById(id);
        tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
@@ -66,16 +70,21 @@
    @Log(title = "房屋基础信息管理-删除房屋", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除房屋")
    @DeleteMapping(value = "/deleteHouseById")
    @PreAuthorize("@ss.hasPermi('system:house:delete')")
    public R<Boolean> deleteHouseById(@RequestParam String id) {
        return R.ok(tHouseService.removeById(id));
    }
    @ApiOperation(value = "获取房屋分页列表")
    @PostMapping(value = "/houseList")
    @PreAuthorize("@ss.hasPermi('system:house:list')")
    public R<PageInfo<THouse>> houseList(@RequestBody THouseQuery query) {
        return R.ok(tHouseService.houseList(query));
    }
    @ApiOperation(value = "历史租户列表")
    @PostMapping(value = "/userHistoryList")
    @PreAuthorize("@ss.hasPermi('system:house:historyList')")
    public R<PageInfo<HouseVO>> userHistoryList(@RequestBody TUserHistoryQuery query) {
        return R.ok(tHouseService.userHistoryList(query));
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
New file
@@ -0,0 +1,183 @@
package com.ruoyi.web.controller.task;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TContractService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
 * @date 2023/7/11 8:39
 */
@Component
public class TaskUtil {
    @Autowired
    private TContractService contractService;
    @Autowired
    private TBillService billService;
    // 每天凌晨00点执行的定时任务 用于合同生成第一笔账单
    @Scheduled(cron = "0 0 0 * * ?")
    public void dayOfFirstBill() {
        try {
            // 查询所有已签订的合同并且未生成第一笔账单的
            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4).isNull(TContract::getFirstPayTime).list();
            List<TBill> bills = new ArrayList<>();
            for (TContract contract : list) {
                contract.setFirstPayTime(contract.getStartTime().plusDays(10));
                // 第一次应缴费日期
                LocalDateTime firstPayTime = contract.getStartTime().plusDays(10);
                LocalDate localDate = contract.getStartTime().plusDays(10).toLocalDate();
                LocalDate now = LocalDate.now();
                // 如果应缴费日期和当前时间不相同 跳过
                if (!localDate.equals(now)) {
                    continue;
                }
                TBill rentBill = new TBill();
                rentBill.setContractId(contract.getId());
                rentBill.setContractNumber(contract.getContractNumber());
                LocalDateTime startPayTime = contract.getStartPayTime();
                LocalDateTime endTime1 = contract.getEndTime();
                // 计算两个时间相差多少天
                long days = ChronoUnit.DAYS.between(startPayTime, endTime1)+1L;
                // 如果时间小于30天 需要计算每日租金
                if (days<30){
                    rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal("30"),2,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
                }else{
                    rentBill.setPayableFeesMoney(contract.getPayType().equals("1")?contract.getMonthRent():
                            contract.getPayType().equals("2")?contract.getMonthRent().multiply(new BigDecimal("3")):contract.getMonthRent().multiply(new BigDecimal("12")).setScale(2,BigDecimal.ROUND_DOWN));
                }
                rentBill.setPayableFeesTime(firstPayTime);
                rentBill.setPayFeesStatus("1");
                rentBill.setBillType("1");
                rentBill.setStartTime(contract.getStartPayTime());
                if ((contract.getEndTime().getYear() == contract.getStartTime().getYear()) && (contract.getEndTime().getMonth() == contract.getStartTime().getMonth())) {
                    // 如果同年同月 那么账单周期为合同结束时间
                    rentBill.setEndTime(contract.getEndTime());
                } else {
                    // 否则 取当月最后一天
                    LocalDateTime endTime = contract.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).withSecond(59).withHour(23).withMinute(59);
                    rentBill.setEndTime(endTime);
                }
                // 租金账单
                bills.add(rentBill);
                // 押金账单
                TBill depositBill = new TBill();
                depositBill.setContractId(contract.getId());
                depositBill.setContractNumber(contract.getContractNumber());
                depositBill.setPayableFeesMoney(contract.getDeposit());
                depositBill.setPayableFeesTime(firstPayTime);
                depositBill.setPayFeesStatus("1");
                depositBill.setBillType("2");
                bills.add(depositBill);
            }
            contractService.updateBatchById(list);
            billService.saveBatch(bills);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 每天凌晨00点执行的定时任务 用于生成合同期最后一笔账单
    @Scheduled(cron = "0 0 0 * * ?")
    public void dayOfEndBill() {
        try {
            // 查询所有已签订的合同并且已经生成第一笔账单的
            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4).isNotNull(TContract::getFirstPayTime).list();
            List<TBill> bills = new ArrayList<>();
            for (TContract contract : list) {
                TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
                        .last("limit 1").one();
                if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))&&beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).isAfter(contract.getEndTime())){
                    TBill tBill = new TBill();
                    tBill.setContractId(contract.getId());
                    tBill.setContractNumber(contract.getContractNumber());
                    tBill.setPayableFeesMoney(contract.getMonthRent());
                    tBill.setPayableFeesTime(LocalDateTime.now());
                    tBill.setPayFeesStatus("1");
                    tBill.setBillType("1");
                    tBill.setStartTime(beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.firstDayOfMonth()));
                    tBill.setEndTime(contract.getEndTime());
                    bills.add(tBill);
                }
            }
            billService.saveBatch(bills);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 每月15号凌晨执行的定时任务 用于生成租金账单
    @Scheduled(cron = "0 0 0 15 * ?")
    public void monthOfBill() {
        try {
            // 查询所有已签订的合同 且合同时间大于15号
            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4)
                    .isNotNull(TContract::getFirstPayTime)
                    .ge(TContract::getEndTime, LocalDateTime.now())
                    .list();
            List<TBill> bills = new ArrayList<>();
            for (TContract contract : list) {
                TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
                        .last("limit 1").one();
                if (beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))continue;
                if (beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).isBefore(contract.getEndTime())){
                    TBill tBill = new TBill();
                    tBill.setContractId(contract.getId());
                    tBill.setContractNumber(contract.getContractNumber());
                    tBill.setPayableFeesMoney(contract.getMonthRent());
                    tBill.setPayableFeesTime(LocalDateTime.now());
                    tBill.setPayFeesStatus("1");
                    tBill.setBillType("1");
                    tBill.setStartTime(beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.firstDayOfMonth()));
                    tBill.setEndTime(beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()));
                    bills.add(tBill);
                }
            }
            billService.saveBatch(bills);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now().minusMonths(1).withDayOfMonth(31);
        System.err.println(now);
        LocalDateTime now2 = now.plusMonths(1);
        System.err.println(now2);
        LocalDateTime now1 = LocalDateTime.now();
        long days = ChronoUnit.DAYS.between(now, now1);
        long days2 = ChronoUnit.DAYS.between(now.plusDays(1), now1);
        System.err.println(days);
        System.err.println(days2);
//        LocalDateTime endTime = now.with(TemporalAdjusters.lastDayOfMonth()).withSecond(59).withHour(23).withMinute(59);
//
//        System.err.println(endTime);
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/PayController.java
@@ -1,17 +1,30 @@
package com.ruoyi.web.controller.api;
import cn.hutool.core.collection.CollectionUtil;
import com.ruoyi.common.constant.AmountConstant;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.dto.MakeOrderDto;
import com.ruoyi.system.dto.MakeOrderResp;
import com.ruoyi.system.dto.OfflinePayDto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TBillConfirm;
import com.ruoyi.system.service.TBillConfirmService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TPayOrderService;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
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.RestController;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
@RestController
@RequestMapping("/t-pay")
@@ -22,6 +35,12 @@
    @Autowired
    TPayOrderService tPayOrderService;
    @Autowired
    TBillService tBillService;
    @Autowired
    TBillConfirmService tBillConfirmService;
    @ApiOperation(value = "创建支付订单")
    @PostMapping("makeOrder")
    public R<MakeOrderResp> makeOrder(@Validated @RequestBody MakeOrderDto dto){
@@ -30,6 +49,23 @@
    }
    @PostMapping("offlinePay")
    public R offlinePay(@Validated @RequestBody OfflinePayDto dto){
        List<TBill> tBills = tBillService.listByIds(dto.getBillIds());
        for (TBill tBill : tBills) {
            TBill save = new TBill();
            save.setId(tBill.getId());
            save.setPayFeesType(2);
            save.setVoucher(dto.getVoucher());
            save.setPayFeesStatus("2");
            tBillService.lockAndUpdateInfo(save);
        }
        TBillConfirm confirm = new TBillConfirm();
        confirm.setBillId(CollectionUtil.join(dto.getBillIds(),","));
        confirm.setVoucher(dto.getVoucher());
        confirm.setPayFeesMoney(new BigDecimal(dto.getAmount()).divide(AmountConstant.b100).setScale(2, RoundingMode.HALF_DOWN).doubleValue());
        tBillConfirmService.save(confirm);
        return R.ok();
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillConfirmController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 账单线下缴费关联表 前端控制器
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@RestController
@RequestMapping("/t-bill-confirm")
public class TBillConfirmController {
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -1,18 +1,30 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.DictConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.dto.TInvoiceDTO;
import com.ruoyi.system.model.*;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.service.TBillDetailService;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TInvoiceService;
import com.ruoyi.system.service.TInvoiceToBillService;
import com.ruoyi.system.vo.TBillVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
@@ -22,13 +34,21 @@
 * @author xiaochen
 * @since 2025-01-17
 */
@Api(tags = "缴费账单")
@RestController
@RequestMapping("/t-bill")
public class TBillController {
    @Autowired
    TBillService tBillService;
    @Autowired
    TBillDetailService billDetailService;
    @Autowired
    TInvoiceService invoiceService;
    @Autowired
    TInvoiceToBillService invoiceToBillService;
    @ApiOperation(value = "缴费账单查询分页列表")
    @PostMapping("list")
    public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){
        if (StringUtils.isEmpty(query.getUserId())){
@@ -38,6 +58,43 @@
        return R.ok(pageInfo);
    }
    @ApiOperation(value = "查看缴费账单详情")
    @GetMapping(value = "/getDetailById")
    public R<TBillVO> getDetailById(@RequestParam String id) {
        TBill bill = tBillService.getById(id);
        TBillVO billVO = new TBillVO();
        BeanUtils.copyProperties(bill, billVO);
        // 查询水电费列表
        if("3".equals(bill.getBillType())){
            List<TBillDetail> list = billDetailService.list(Wrappers.lambdaQuery(TBillDetail.class)
                    .eq(TBillDetail::getBillId, id));
            billVO.setBillDetailList(list);
        }
        billVO.setBillType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_BILL_TYPE,billVO.getBillType()));
        billVO.setPayFeesStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_PAY_FEES_STATUS,billVO.getPayFeesStatus()));
        return R.ok(billVO);
    }
    @ApiOperation(value = "缴费账单开票")
    @PostMapping(value = "/invoice")
    public R<String> invoice(@RequestBody TInvoiceDTO dto) {
        // 添加开票信息
        invoiceService.save(dto);
        // 添加开票信息中间表信息
        List<String> billIds = dto.getBillIds();
        List<TInvoiceToBill> sysInvoiceToBills = new ArrayList<>();
        for (String billId : billIds) {
            TInvoiceToBill tInvoiceToBill = new TInvoiceToBill();
            tInvoiceToBill.setInvoiceId(dto.getId());
            tInvoiceToBill.setBillId(billId);
            sysInvoiceToBills.add(tInvoiceToBill);
        }
        invoiceToBillService.saveBatch(sysInvoiceToBills);
        return R.ok();
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
@@ -1,6 +1,17 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.model.TInformation;
import com.ruoyi.system.query.TInformationQuery;
import com.ruoyi.system.service.TInformationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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.RestController;
@@ -13,9 +24,25 @@
 * @author xiaochen
 * @since 2025-01-17
 */
@Api(tags = "资讯管理")
@RestController
@RequestMapping("/t-information")
public class TInformationController {
    private final TInformationService informationService;
    @Autowired
    public TInformationController(TInformationService informationService) {
        this.informationService = informationService;
    }
    /**
     * 获取资讯管理管理列表
     */
    @ApiOperation(value = "获取资讯管理分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TInformation>> pageList(@RequestBody TInformationQuery query) {
        return R.ok(informationService.pageList(query));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -66,7 +66,7 @@
    @PostMapping("/list")
    public AjaxResult list(@RequestBody SysRoleQuery query)
    {
        PageInfo<SysRole> list = roleService.selectList(query);
        PageInfo<SysRole> list = roleService.selectPageList(query);
        return AjaxResult.success(list);
    }
ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
@@ -39,4 +39,8 @@
     * 缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 5=已失效
     */
    public static final String DICT_TYPE_PAY_FEES_STATUS = "t_pay_fees_status";
    /**
     * 账单类型 1=租金 2=押金 3=生活费用
     */
    public static final String DICT_TYPE_BILL_TYPE = "t_bill_type";
}
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -1,16 +1,14 @@
package com.ruoyi.common.core.redis;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
/**
@@ -22,6 +20,15 @@
@Component
public class RedisCache
{
    private static final String LOCK_PREFIX = "lock:";
    private static final RedisScript<Long> UNLOCK_SCRIPT = new DefaultRedisScript<>(
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                    "  return redis.call('del', KEYS[1]) " +
                    "else " +
                    "  return 0 " +
                    "end",
            Long.class
    );
    @Autowired
    public RedisTemplate redisTemplate;
@@ -265,4 +272,33 @@
    {
        return redisTemplate.keys(pattern);
    }
    /**
     * 尝试加锁
     *
     * @param lockKey   锁的key
     * @param requestId 锁的持有者标识符(如UUID)
     * @param expireTime 锁的过期时间(秒)
     * @return 加锁成功返回true,否则返回false
     */
    public boolean tryLock(String lockKey, String requestId, long expireTime) {
        String lockKeyWithPrefix = LOCK_PREFIX + lockKey;
        // 使用SET命令的NX和PX选项来加锁
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKeyWithPrefix, requestId, expireTime, TimeUnit.SECONDS);
        return result != null && result;
    }
    /**
     * 解锁
     *
     * @param lockKey   锁的key
     * @param requestId 锁的持有者标识符(如UUID)
     * @return 解锁成功返回true,否则返回false
     */
    public boolean unlock(String lockKey, String requestId) {
        String lockKeyWithPrefix = LOCK_PREFIX + lockKey;
        // 使用Lua脚本来验证锁的持有者并解锁
        Long result = (Long) redisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(lockKeyWithPrefix), requestId);
        return result != null && result == 1L;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/OfflinePayDto.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.system.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
@Data
public class OfflinePayDto implements Serializable {
    /**
     * 用户ID
     */
    @ApiModelProperty(value = "用户ID")
    private String userId;
    @ApiModelProperty(value = "支付金额,单位:分")
    @NotNull(message = "金额不能为空")
    private Long amount;
    /**
     * 账单列表
     */
    @ApiModelProperty(value = "账单列表")
    @NotEmpty(message = "账单ID不能为空")
    private List<String> billIds;
    /**
     * 凭证文件ID
     */
    @ApiModelProperty(value = "凭证文件ID")
    @NotEmpty(message = "凭证文件不能为空")
    private String voucher;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/TBillDto.java
@@ -16,4 +16,5 @@
    private String houseName;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/TInvoiceDTO.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.system.dto;
import com.ruoyi.system.model.TInvoice;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "开票DTO")
public class TInvoiceDTO extends TInvoice {
    @ApiModelProperty(value = "账单id集合")
    private List<String> billIds;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/TbillSaveDto.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.system.dto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TBillDetail;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class TbillSaveDto extends TBill implements Serializable {
    @ApiModelProperty(value = "水单费列表")
    private List<TBillDetail> details;
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillConfirmMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.model.TBillConfirm;
/**
 * <p>
 * 账单线下缴费关联表 Mapper 接口
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
public interface TBillConfirmMapper extends BaseMapper<TBillConfirm> {
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBillDetailMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.model.TBillDetail;
/**
 * <p>
 * 账单水电费子表 Mapper 接口
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
public interface TBillDetailMapper extends BaseMapper<TBillDetail> {
}
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInvoiceToBillMapper.java
@@ -1,7 +1,7 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.model.TInvoiceToBill;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.model.TInvoiceToBill;
/**
 * <p>
ruoyi-system/src/main/java/com/ruoyi/system/model/TBill.java
@@ -8,6 +8,7 @@
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
@@ -16,6 +17,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Transient;
/**
 * <p>
ruoyi-system/src/main/java/com/ruoyi/system/model/TBillConfirm.java
New file
@@ -0,0 +1,46 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
 * <p>
 * 账单线下缴费关联表
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_bill_confirm")
@ApiModel(value="TBillConfirm对象", description="账单线下缴费关联表")
public class TBillConfirm implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "账单id,逗号分隔")
    @TableField("bill_id")
    private String billId;
    @ApiModelProperty(value = "缴费金额")
    @TableField("pay_fees_money")
    private Double payFeesMoney;
    @ApiModelProperty(value = "凭证上传")
    @TableField("voucher")
    private String voucher;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TBillDetail.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
 * 账单水电费子表
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_bill_detail")
@ApiModel(value="TBillDetail对象", description="账单水电费子表")
public class TBillDetail extends BaseModel {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "账单id")
    @TableField("bill_id")
    private String billId;
    @ApiModelProperty(value = "初始读数")
    @TableField("start_reading")
    private BigDecimal startReading;
    @ApiModelProperty(value = "结束读数")
    @TableField("end_reading")
    private BigDecimal endReading;
    @ApiModelProperty(value = "使用量")
    @TableField("usage_measure")
    private BigDecimal usageMeasure;
    @ApiModelProperty(value = "单价")
    @TableField("unit_price")
    private BigDecimal unitPrice;
    @ApiModelProperty(value = "总金额")
    @TableField("total_amount")
    private BigDecimal totalAmount;
    @ApiModelProperty(value = "费用类型 1=水费 2=电费")
    @TableField("live_type")
    private Integer liveType;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
@@ -52,6 +52,10 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("end_time")
    private LocalDateTime endTime;
    @ApiModelProperty(value = "开始计费时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("start_pay_time")
    private LocalDateTime startPayTime;
    @ApiModelProperty(value = "每月租金")
    @TableField("month_rent")
@@ -65,7 +69,7 @@
    @TableField("pay_type")
    private String payType;
    @ApiModelProperty(value = "第一次支付日期")
    @ApiModelProperty(value = "账单第一次支付日期 合同生效日期+10天 (不是真正的支付日期)生成第一次帐单后存值")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("first_pay_time")
    private LocalDateTime firstPayTime;
ruoyi-system/src/main/java/com/ruoyi/system/model/TInvoiceToBill.java
@@ -1,13 +1,15 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
 * <p>
@@ -25,7 +27,7 @@
    private static final long serialVersionUID = 1L;
    @TableId("id")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "开票id")
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillConfirmService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.TBillConfirm;
/**
 * <p>
 * 账单线下缴费关联表 服务类
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
public interface TBillConfirmService extends IService<TBillConfirm> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillDetailService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.TBillDetail;
/**
 * <p>
 * 账单水电费子表 服务类
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
public interface TBillDetailService extends IService<TBillDetail> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TBillService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.dto.TbillSaveDto;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.query.TBillQuery;
@@ -18,4 +19,7 @@
    PageInfo<TBillDto> queryPage(TBillQuery query);
    Boolean lockAndUpdateInfo(TBill save);
    void saveBill(TbillSaveDto bill);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeptService.java
@@ -1,7 +1,6 @@
package com.ruoyi.system.service;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.dto.TDeptUpAndDownDTO;
import com.ruoyi.system.model.TDept;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.query.TDeptQuery;
ruoyi-system/src/main/java/com/ruoyi/system/service/TInvoiceToBillService.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.TInvoiceToBill;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.system.model.TInvoice;
import com.ruoyi.system.model.TInvoiceToBill;
@@ -18,6 +20,7 @@
 * @since 2025-02-10
 */
public interface TInvoiceToBillService extends IService<TInvoiceToBill> {
    List<TInvoiceToBill> makeQuery(TInvoiceToBillQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillConfirmServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.TBillConfirmMapper;
import com.ruoyi.system.model.TBillConfirm;
import com.ruoyi.system.service.TBillConfirmService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 账单线下缴费关联表 服务实现类
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@Service
public class TBillConfirmServiceImpl extends ServiceImpl<TBillConfirmMapper, TBillConfirm> implements TBillConfirmService {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillDetailServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.TBillDetailMapper;
import com.ruoyi.system.model.TBillDetail;
import com.ruoyi.system.service.TBillDetailService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 账单水电费子表 服务实现类
 * </p>
 *
 * @author xiaochen
 * @since 2025-02-10
 */
@Service
public class TBillDetailServiceImpl extends ServiceImpl<TBillDetailMapper, TBillDetail> implements TBillDetailService {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -4,17 +4,23 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.dto.TbillSaveDto;
import com.ruoyi.system.mapper.TBillMapper;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TBillDetail;
import com.ruoyi.system.model.TContract;
import com.ruoyi.system.model.THouse;
import com.ruoyi.system.query.TBillQuery;
import com.ruoyi.system.service.TBillDetailService;
import com.ruoyi.system.service.TBillService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
@@ -35,6 +41,10 @@
    @Autowired
    TBillMapper tBillMapper;
    @Autowired
    TBillDetailService tBillDetailService;
    public PageInfo<TBillDto> queryPage(TBillQuery query){
        PageInfo<TBill> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        PageInfo<TBillDto> info = tBillMapper.page(pageInfo, query);
@@ -42,17 +52,32 @@
    }
    /**
     * 传的金额
     * @param tBill
     * @return
     */
    public Boolean checkAndUpdateBill(TBill tBill){
    public Boolean lockAndUpdateInfo(TBill tBill){
        if (StringUtils.isEmpty(tBill.getId())){
            throw new ServiceException("账单主键ID不能为空");
        }
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBill(TbillSaveDto bill) {
        save(bill);
        if (bill.getBillType().equals("3")){
            if (bill.getDetails()==null || bill.getDetails().size()==0){
                throw new ServiceException("生活费用列表不能为空");
            }
            for (TBillDetail detail : bill.getDetails()) {
                detail.setBillId(bill.getId());
                tBillDetailService.save(detail);
            }
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeptServiceImpl.java
@@ -3,7 +3,7 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TDeptUpAndDownDTO;
import com.ruoyi.system.mapper.SysMenuMapper;
import com.ruoyi.system.model.TDept;
import com.ruoyi.system.mapper.TDeptMapper;
import com.ruoyi.system.query.TDeptQuery;
@@ -13,7 +13,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -27,6 +26,8 @@
@Service
public class TDeptServiceImpl extends ServiceImpl<TDeptMapper, TDept> implements TDeptService {
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Override
    public boolean isExit(TDept dto) {
        if(StringUtils.isNotEmpty(dto.getDeptId())){
@@ -46,4 +47,5 @@
        return pageInfo;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInvoiceToBillServiceImpl.java
@@ -12,6 +12,12 @@
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.TInvoiceToBillMapper;
import com.ruoyi.system.model.TInvoiceToBill;
import com.ruoyi.system.service.TInvoiceToBillService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 账单开票中间表 服务实现类
ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.system.vo;
import com.ruoyi.system.model.TBill;
import com.ruoyi.system.model.TBillDetail;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "缴费账单VO")
public class TBillVO extends TBill {
    @ApiModelProperty(value = "水电费明细")
    private List<TBillDetail> billDetailList;
}
ruoyi-system/src/main/resources/mapper/system/TBillConfirmMapper.xml
New file
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TBillConfirmMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TBillConfirm">
        <id column="id" property="id" />
        <result column="bill_id" property="billId" />
        <result column="pay_fees_money" property="payFeesMoney" />
        <result column="voucher" property="voucher" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, bill_id, pay_fees_money, voucher
    </sql>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TBillDetailMapper.xml
New file
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TBillDetailMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TBillDetail">
        <id column="id" property="id" />
        <result column="bill_id" property="billId" />
        <result column="start_reading" property="startReading" />
        <result column="end_reading" property="endReading" />
        <result column="usage_measure" property="usageMeasure" />
        <result column="unit_price" property="unitPrice" />
        <result column="total_amount" property="totalAmount" />
        <result column="live_type" property="liveType" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
        <result column="update_by" property="updateBy" />
        <result column="disabled" property="disabled" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, bill_id, start_reading, end_reading, usage_measure, unit_price, total_amount,live_type, create_time, update_time, create_by, update_by, disabled
    </sql>
</mapper>
ruoyi-system/src/main/resources/mapper/system/TBillMapper.xml
@@ -42,10 +42,11 @@
            h.house_name as houseName
        FROM
            t_bill b
        LEFT JOIN t_contract c ON c.contract_number = b.contract_number
        LEFT JOIN t_house h ON h.id = c.house_id
        LEFT JOIN t_tenant t ON t.id = c.tenant_id
        LEFT JOIN t_contract c ON c.contract_number = b.contract_number and c.disabled=0
        LEFT JOIN t_house h ON h.id = c.house_id and h.disabled=0
        LEFT JOIN t_tenant t ON t.id = c.tenant_id and t.disabled=0
        <where>
            b.disabled=0
            <if test="query.payFeesStatus != null">
                and b.pay_fees_status = #{query.payFeesStatus}
            </if>
ruoyi-system/src/main/resources/mapper/system/TInvoiceToBillMapper.xml
New file
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TInvoiceToBillMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TInvoiceToBill">
        <id column="id" property="id" />
        <result column="invoice_id" property="invoiceId" />
        <result column="bill_id" property="billId" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, invoice_id, bill_id
    </sql>
</mapper>