Merge branch 'xizang-changyun' of https://gitee.com/xiaochen991015/xizang
Conflicts:
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
| | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TBankFlowService; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import com.ruoyi.system.vo.TBankFlowStatisticsVo; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | |
| | | public R<PageInfo<TBankFlow>> list(@RequestBody TBankFlowQuery query) { |
| | | return R.ok(flowService.pageList(query)); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据支付方式统计流水金额") |
| | | @PostMapping("/getPaymentStats") |
| | | public R<TBankFlowStatisticsVo> getPaymentStats(@RequestBody TBankFlowQuery query){ |
| | | return R.ok(flowService.getPaymentStats(query)); |
| | | } |
| | | } |
| | | |
| | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.system.dto.OfflinePayCheckDto; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.dto.TbillSaveDto; |
| | | import com.ruoyi.system.dto.*; |
| | | import com.ruoyi.system.model.TBill; |
| | | import com.ruoyi.system.query.TBillQuery; |
| | | import com.ruoyi.system.service.TBillService; |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | @PreAuthorize("@ss.hasPermi('system:bill:sendSmsByBillIds')") |
| | | @ApiOperation("账单批量发送短信通知") |
| | | @PostMapping("sendSmsByBillIds") |
| | | public R sendSmsByBillIds(@Validated @RequestBody SmsByBillDto dto){ |
| | | Integer failNum = tBillService.sendSmsByBillIds(dto); |
| | | return R.ok(failNum); |
| | | } |
| | | |
| | | |
| | | @PreAuthorize("@ss.hasPermi('system:bill:sendMailBatchByBillIds')") |
| | | @ApiOperation("账单批量发送短信通知") |
| | | @PostMapping("sendMailBatchByBillIds") |
| | | public R sendMailBatchByBillIds(@Validated @RequestBody SmsByBillDto dto){ |
| | | Integer failNum = tBillService.sendMailBatchByBillIds(dto); |
| | | return R.ok(failNum); |
| | | } |
| | | |
| | | @PreAuthorize("@ss.hasPermi('system:bill:cashPay')") |
| | | @ApiOperation("收款") |
| | | @PostMapping("cashPay") |
| | | public R cashPay(@RequestBody OfflinePayDto offlinePayDto){ |
| | | return null; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | @ApiOperation(value = "测试生成账单") |
| | | @PostMapping(value = "/testBill") |
| | | public R testBill(String id) { |
| | | SignContractDTO signContractDTO = new SignContractDTO(); |
| | | signContractDTO.setId(id); |
| | | contractService.signContract(signContractDTO); |
| | | TContract contract = contractService.getById(id); |
| | | // 查询所有已签订的合同并且未生成第一笔账单的 |
| | | |
| | | List<TBill> bills = new ArrayList<>(); |
| | | List<TContractRentType> contractRentTypes = contractRentTypeService.list(); |
| | | contract.setFirstPayTime(contract.getStartTime().plusDays(10)); |
| | | // 第一次应缴费日期 |
| | | LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0); |
| | | TBill rentBill = new TBill(); |
| | | rentBill.setContractId(contract.getId()); |
| | | rentBill.setContractNumber(contract.getContractNumber()); |
| | | rentBill.setPayableFeesTime(firstPayTime.toLocalDate()); |
| | | rentBill.setPayFeesStatus("1"); |
| | | rentBill.setBillType("1"); |
| | | rentBill.setStartTime(contract.getStartPayTime()); |
| | | TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null); |
| | | |
| | | if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){ |
| | | // 计算租金变动的天数 |
| | | long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L; |
| | | contract.setChangeTime(LocalDateTime.now()); |
| | | // 递增递减的租金 |
| | | BigDecimal contractRentTypeMoney = new BigDecimal("0"); |
| | | // 不递增递减的租金 |
| | | BigDecimal originalMoney = new BigDecimal("0"); |
| | | // 原租金 |
| | | switch (tContractRentType.getIncreasingDecreasingType()){ |
| | | case 1: |
| | | switch (tContractRentType.getIncreasingDecreasing()){ |
| | | case 1: |
| | | contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays))); |
| | | contract.setChangeRent(contractRentTypeMoney); |
| | | break; |
| | | case 2: |
| | | contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN)); |
| | | contract.setChangeRent(contractRentTypeMoney); |
| | | break; |
| | | } |
| | | break; |
| | | case 2: |
| | | switch (tContractRentType.getIncreasingDecreasing()){ |
| | | case 1: |
| | | contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)); |
| | | contract.setChangeRent(contractRentTypeMoney); |
| | | break; |
| | | case 2: |
| | | contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)); |
| | | contract.setChangeRent(contractRentTypeMoney); |
| | | |
| | | break; |
| | | } |
| | | break; |
| | | } |
| | | // 不需要涨租金的时间段 |
| | | if (contract.getFirstPayTime().isBefore(tContractRentType.getChangeTime())){ |
| | | long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime()); |
| | | originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN)) |
| | | .multiply(new BigDecimal(originalDays)); |
| | | rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney)); |
| | | rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney()); |
| | | }else{ |
| | | rentBill.setPayableFeesMoney(contractRentTypeMoney); |
| | | rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney()); |
| | | } |
| | | |
| | | if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){ |
| | | rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12)); |
| | | }else{ |
| | | rentBill.setEndTime(contract.getEndTime()); |
| | | } |
| | | }else{ |
| | | if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){ |
| | | rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12)); |
| | | }else{ |
| | | rentBill.setEndTime(contract.getEndTime()); |
| | | } |
| | | // 不走递增递减 |
| | | long allDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), rentBill.getEndTime()); |
| | | rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays))); |
| | | rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney()); |
| | | |
| | | } |
| | | // 租金账单 |
| | | bills.add(rentBill); |
| | | // 押金账单 |
| | | TBill depositBill = new TBill(); |
| | | depositBill.setContractId(contract.getId()); |
| | | depositBill.setContractNumber(contract.getContractNumber()); |
| | | depositBill.setPayableFeesMoney(contract.getDeposit()); |
| | | depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney()); |
| | | |
| | | depositBill.setPayableFeesTime(firstPayTime.toLocalDate()); |
| | | depositBill.setPayFeesStatus("1"); |
| | | depositBill.setBillType("2"); |
| | | contractService.updateById(contract); |
| | | billService.save(rentBill); |
| | | billService.save(depositBill); |
| | | return R.ok(); |
| | | } |
| | | @ApiOperation(value = "获取合同分页列表") |
| | |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import com.ruoyi.system.vo.TFlowManagementStatisticsVo; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | |
| | | return R.ok(flowService.pageList(query)); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据支付方式统计流水金额") |
| | | @PostMapping("/getPaymentStats") |
| | | public R<TFlowManagementStatisticsVo> getPaymentStats(@RequestBody TFlowManagementQuery query){ |
| | | return R.ok(flowService.getPaymentStats(query)); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | @ApiOperation(value = "关联账单信息") |
| | | @GetMapping(value = "/getBillByInvoiceId") |
| | | public R<PageInfo<TBill>> getBillByInvoiceId(String invoiceId){ |
| | | @GetMapping(value = "/getBillByInvoiceId/{invoiceId}") |
| | | public R<PageInfo<TBill>> getBillByInvoiceId(@PathVariable String invoiceId){ |
| | | return R.ok(tBillService.getBillByInvoiceId(invoiceId)); |
| | | } |
| | | |
| | |
| | | TInvoice tInvoice = new TInvoice(); |
| | | tInvoice.setId(query.getId()); |
| | | tInvoice.setInvoiceVoucher(query.getInvoiceVoucher()); |
| | | tInvoice.setInvoiceVoucherName(query.getInvoiceVoucherName()); |
| | | tInvoice.setInvoiceTime(query.getInvoiceTime()); |
| | | tInvoice.setStatus(2); |
| | | return R.ok(invoiceService.updateById(tInvoice)); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, 1).list(); |
| | | for (TBill tBill : list) { |
| | | TContract contract = contractService.getById(tBill.getContractId()); |
| | | LocalDateTime payableFeesTime = tBill.getPayableFeesTime(); |
| | | LocalDate payableFeesTime = tBill.getPayableFeesTime(); |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | // 计算两个时间相差多少个小时 |
| | | long hours = ChronoUnit.HOURS.between(payableFeesTime, now); |
| | |
| | | try { |
| | | List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, "2").list(); |
| | | for (TBill tBill : list) { |
| | | if (tBill.getPayableFeesTime().toLocalDate().equals(LocalDate.now())){ |
| | | if (tBill.getPayableFeesTime().equals(LocalDate.now())){ |
| | | tBill.setPayFeesStatus("1"); |
| | | } |
| | | } |
| | |
| | | <artifactId>jave-all-deps</artifactId> |
| | | <version>2.5.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.tencentcloudapi</groupId> |
| | | <artifactId>tencentcloud-sdk-java</artifactId> |
| | | <version>4.0.11</version> |
| | | </dependency> |
| | | |
| | | <!-- 工作流--> |
| | | <dependency> |
New file |
| | |
| | | package com.ruoyi.common.config; |
| | | |
| | | import com.tencentcloudapi.common.Credential; |
| | | import com.tencentcloudapi.common.profile.ClientProfile; |
| | | import com.tencentcloudapi.common.profile.HttpProfile; |
| | | import com.tencentcloudapi.sms.v20190711.SmsClient; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | @EnableConfigurationProperties(SmsProperties.class) |
| | | @ConditionalOnProperty(value = SmsProperties.ENABLE_KEY,matchIfMissing = true) |
| | | public class SmsConfig { |
| | | |
| | | @Bean |
| | | public SmsClient smsClient(SmsProperties properties) { |
| | | // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId,SecretKey。 |
| | | // 为了保护密钥安全,建议将密钥设置在环境变量中或者配置文件中,请参考凭证管理 https://github.com/TencentCloud/tencentcloud-sdk-java?tab=readme-ov-file#%E5%87%AD%E8%AF%81%E7%AE%A1%E7%90%86。 |
| | | // 硬编码密钥到代码中有可能随代码泄露而暴露,有安全隐患,并不推荐。 |
| | | // SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi |
| | | // Credential cred = new Credential("SecretId", "SecretKey"); |
| | | |
| | | Credential cred = new Credential(properties.getSecretid(), properties.getSecretkey()); |
| | | // 实例化一个http选项,可选的,没有特殊需求可以跳过 |
| | | HttpProfile httpProfile = new HttpProfile(); |
| | | // 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com |
| | | httpProfile.setEndpoint("sms.tencentcloudapi.com"); |
| | | // 实例化一个客户端配置对象 |
| | | ClientProfile clientProfile = new ClientProfile(); |
| | | clientProfile.setHttpProfile(httpProfile); |
| | | // 实例化要请求产品(sms)的client对象,第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 |
| | | return new SmsClient(cred, "ap-guangzhou", clientProfile); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.config; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | @Data |
| | | @ConfigurationProperties(prefix = "sms") |
| | | public class SmsProperties { |
| | | |
| | | public static final String ENABLE_KEY = "sms.enable"; |
| | | |
| | | private Boolean enable; |
| | | |
| | | private String appId; |
| | | |
| | | private String secretid; |
| | | |
| | | private String secretkey; |
| | | /** |
| | | * 短信签名 |
| | | */ |
| | | private String sign; |
| | | |
| | | /** |
| | | * 账单提醒 ,同一个用户离上次发送短信的最小间隔 |
| | | * 单位分钟 |
| | | */ |
| | | private Integer billSmsDelayPeriod = 60; |
| | | /** |
| | | * 账单提醒 ,同一个用户离上次发送邮件的最小间隔 |
| | | * 单位分钟 |
| | | */ |
| | | private Integer billMailDelayPeriod = 60; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.utils; |
| | | |
| | | import com.ruoyi.common.config.SmsProperties; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.tencentcloudapi.common.exception.TencentCloudSDKException; |
| | | import com.tencentcloudapi.sms.v20190711.SmsClient; |
| | | import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest; |
| | | import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | @Component |
| | | @Slf4j |
| | | public class SmsUtil { |
| | | |
| | | @Resource |
| | | SmsProperties smsProperties; |
| | | @Resource |
| | | SmsClient smsClient; |
| | | |
| | | |
| | | public SmsProperties getPro(){ |
| | | return smsProperties; |
| | | } |
| | | |
| | | public boolean sendSms(String phone,String templateId,String[] param){ |
| | | SendSmsRequest req = new SendSmsRequest(); |
| | | req.setSmsSdkAppid(smsProperties.getAppId()); |
| | | req.setPhoneNumberSet(new String[]{phone}); |
| | | req.setTemplateID(templateId); |
| | | req.setSign(smsProperties.getSign()); |
| | | req.setTemplateParamSet(param); |
| | | req.setSenderId(""); |
| | | req.setSessionContext(""); |
| | | req.setExtendCode(""); |
| | | try { |
| | | smsClient.SendSms(req); |
| | | return true; |
| | | } catch (TencentCloudSDKException e) { |
| | | log.error("发送短信失败,{},{}",phone,param,e); |
| | | throw new ServiceException("发送短信失败"); |
| | | } catch (Exception e){ |
| | | log.error("发送短信失败1,{},{}",phone,param,e); |
| | | throw new ServiceException("发送短信失败1"); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotEmpty; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class SmsByBillDto implements Serializable { |
| | | |
| | | @NotEmpty(message = "账单ID不能为空") |
| | | private List<String> billIds; |
| | | |
| | | private String sendUserId; |
| | | |
| | | } |
| | |
| | | |
| | | private String phone; |
| | | |
| | | private String email; |
| | | |
| | | private String account; |
| | | |
| | | private String houseName; |
| | |
| | | @Data |
| | | public class TbillSaveDto extends TBill implements Serializable { |
| | | |
| | | @ApiModelProperty(value = "水单费列表") |
| | | @ApiModelProperty(value = "水电费列表") |
| | | private List<TBillDetail> details; |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.vo.TBankFlowStatisticsVo; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @since 2025-02-07 |
| | | */ |
| | | public interface TBankFlowMapper extends BaseMapper<TBankFlow> { |
| | | TBankFlowStatisticsVo getPaymentStats(@Param("req") TBankFlowQuery query); |
| | | |
| | | } |
| | |
| | | * @return |
| | | */ |
| | | List<TBillDto> invoiceList(@Param("query")TBillQuery query, @Param("pageInfo")PageInfo<TBillDto> pageInfo); |
| | | |
| | | TBillDto selectTenentByBillId(@Param("billId") String billId); |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.vo.TFlowManagementStatisticsVo; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @since 2025-01-17 |
| | | */ |
| | | public interface TFlowManagementMapper extends BaseMapper<TFlowManagement> { |
| | | |
| | | TFlowManagementStatisticsVo getPaymentStats(@Param("req") TFlowManagementQuery query); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | |
| | | @ApiModelProperty(value = "应缴费日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") |
| | | @TableField("payable_fees_time") |
| | | private LocalDateTime payableFeesTime; |
| | | private LocalDate payableFeesTime; |
| | | |
| | | @ApiModelProperty(value = "缴费状态 1=未缴费 2=待确认 3=已缴费 4=已逾期 5= 已失效") |
| | | @TableField("pay_fees_status") |
| | |
| | | @TableField("confirm_id") |
| | | private String confirmId; |
| | | |
| | | @ApiModelProperty(value = "短信发送状态:0.未发送 1.已发送 2.发送失败") |
| | | @TableField("sms_status") |
| | | private Integer smsStatus; |
| | | |
| | | @ApiModelProperty(value = "短信最后发送时间") |
| | | @TableField("sms_last_time") |
| | | private Date smsLastTime; |
| | | |
| | | @ApiModelProperty(value = "最后短信发送人") |
| | | @TableField("sms_send_userid") |
| | | private String smsSendUserid; |
| | | |
| | | |
| | | @ApiModelProperty(value = "邮件发送状态:0.未发送 1.已发送 2.发送失败") |
| | | @TableField("mail_status") |
| | | private Integer mailStatus; |
| | | |
| | | @ApiModelProperty(value = "邮件最后发送时间") |
| | | @TableField("mail_last_time") |
| | | private Date mailLastTime; |
| | | |
| | | @ApiModelProperty(value = "最后邮件发送人") |
| | | @TableField("mail_send_userid") |
| | | private String mailSendUserid; |
| | | |
| | | /** |
| | | * 抵扣金额 |
| | | */ |
| | |
| | | @TableField(exist = false) |
| | | private BigDecimal preOutstand; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | @TableField("contract_number") |
| | | private String contractNumber; |
| | | |
| | | @ApiModelProperty(value = "开票文件名称") |
| | | @TableField("invoice_voucher_name") |
| | | private String invoiceVoucherName; |
| | | |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.query; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | |
| | | @ApiModelProperty(value = "开票结束日期") |
| | | private String invoiceEndTime; |
| | | |
| | | @ApiModelProperty(value = "开票文件名称") |
| | | private String invoiceVoucherName; |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.vo.TBankFlowStatisticsVo; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | |
| | | PageInfo<TBankFlow> pageList(TBankFlowQuery query); |
| | | List<TBankFlow> makeQuery(TBankFlowQuery query); |
| | | TBankFlowStatisticsVo getPaymentStats( TBankFlowQuery query); |
| | | |
| | | List<TBankFlow> searchByBankSerialNumber(String bankSerialNumber); |
| | | |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.dto.OfflinePayCheckDto; |
| | | import com.ruoyi.system.dto.SmsByBillDto; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.dto.TbillSaveDto; |
| | | import com.ruoyi.system.model.TBill; |
| | |
| | | * @return |
| | | */ |
| | | PageInfo<TBill> getBillByInvoiceId(String invoiceId); |
| | | |
| | | Integer sendSmsByBillIds(SmsByBillDto dto); |
| | | |
| | | Integer sendMailBatchByBillIds(SmsByBillDto dto); |
| | | } |
| | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.vo.TFlowManagementStatisticsVo; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | public interface TFlowManagementService extends IService<TFlowManagement> { |
| | | PageInfo<TFlowManagement> pageList(TFlowManagementQuery query); |
| | | List<TFlowManagement> makeQuery(TFlowManagementQuery query); |
| | | TFlowManagementStatisticsVo getPaymentStats(TFlowManagementQuery req); |
| | | |
| | | |
| | | |
| | |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.mapper.TBankFlowMapper; |
| | | import com.ruoyi.system.model.TBankFlow; |
| | | import com.ruoyi.system.model.TFlowManagement; |
| | | import com.ruoyi.system.query.TBankFlowQuery; |
| | | import com.ruoyi.system.service.TBankFlowService; |
| | | import com.ruoyi.system.vo.TBankFlowStatisticsVo; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | |
| | | pageInfo.setTotal(list.size()); |
| | | return pageInfo; |
| | | } |
| | | |
| | | @Override |
| | | public List<TBankFlow> makeQuery(TBankFlowQuery query) { |
| | | LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>(); |
| | |
| | | ; |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public TBankFlowStatisticsVo getPaymentStats(TBankFlowQuery query) { |
| | | return this.baseMapper.getPaymentStats(query); |
| | | } |
| | | |
| | | /** |
| | | * 根据银行流水号模糊查询 |
| | | * @param bankSerialNumber |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<TBankFlow> searchByBankSerialNumber(String bankSerialNumber) { |
| | | LambdaQueryWrapper<TBankFlow> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.like(StringUtils.isNotEmpty(bankSerialNumber),TBankFlow::getBankSerialNumber,bankSerialNumber); |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.common.core.redis.RedisCache; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SmsUtil; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.uuid.UUID; |
| | | import com.ruoyi.system.dto.OfflinePayCheckDto; |
| | | import com.ruoyi.system.dto.SmsByBillDto; |
| | | import com.ruoyi.system.dto.TBillDto; |
| | | import com.ruoyi.system.dto.TbillSaveDto; |
| | | import com.ruoyi.system.mapper.TBillMapper; |
| | |
| | | import com.ruoyi.system.query.TInvoiceToBillQuery; |
| | | import com.ruoyi.system.service.*; |
| | | import com.taxi591.bankapi.dto.ChargeBillRequest; |
| | | import com.tencentcloudapi.sms.v20190711.SmsClient; |
| | | import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import org.springframework.beans.BeanUtils; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | import java.math.BigDecimal; |
| | |
| | | |
| | | @Autowired |
| | | TInvoiceToBillService tInvoiceToBillService; |
| | | |
| | | |
| | | @Resource |
| | | SmsUtil smsUtil; |
| | | |
| | | public PageInfo<TBillDto> queryPage(TBillQuery query){ |
| | | PageInfo<TBill> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public Integer sendSmsByBillIds(SmsByBillDto dto) { |
| | | int failNum = 0; |
| | | for (String billId : dto.getBillIds()) { |
| | | TBillDto bill = getTenentByBillId(billId); |
| | | if (bill.getSmsLastTime()!=null |
| | | && (System.currentTimeMillis()-bill.getSmsLastTime().getTime()<smsUtil.getPro().getBillSmsDelayPeriod()*60*1000L)){ |
| | | throw new ServiceException("有账单最近一次发送的时间是:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,bill.getSmsLastTime())); |
| | | } |
| | | if (StringUtils.isEmpty(bill.getPhone())){ |
| | | failNum++; |
| | | continue; |
| | | } |
| | | TBill save = new TBill(); |
| | | save.setId(bill.getId()); |
| | | try { |
| | | smsUtil.sendSms(bill.getPhone(), "", new String[]{""}); |
| | | save.setSmsStatus(1); |
| | | }catch (ServiceException e){ |
| | | failNum++; |
| | | save.setSmsStatus(2); |
| | | } |
| | | save.setSmsLastTime(new Date()); |
| | | save.setSmsSendUserid(dto.getSendUserId()); |
| | | lockAndUpdateInfo(save,1); |
| | | } |
| | | return failNum; |
| | | } |
| | | |
| | | @Override |
| | | public Integer sendMailBatchByBillIds(SmsByBillDto dto) { |
| | | int failNum = 0; |
| | | for (String billId : dto.getBillIds()) { |
| | | TBillDto bill = getTenentByBillId(billId); |
| | | if (bill.getSmsLastTime()!=null |
| | | && (System.currentTimeMillis()-bill.getSmsLastTime().getTime()<smsUtil.getPro().getBillMailDelayPeriod()*60*1000L)){ |
| | | throw new ServiceException("有账单最近一次发送的时间是:"+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,bill.getSmsLastTime())); |
| | | } |
| | | if (StringUtils.isEmpty(bill.getEmail())){ |
| | | failNum++; |
| | | continue; |
| | | } |
| | | TBill save = new TBill(); |
| | | save.setId(bill.getId()); |
| | | try { |
| | | //todo 发送邮件 |
| | | save.setMailStatus(1); |
| | | }catch (ServiceException e){ |
| | | failNum++; |
| | | save.setMailStatus(2); |
| | | } |
| | | save.setMailLastTime(new Date()); |
| | | save.setMailSendUserid(dto.getSendUserId()); |
| | | lockAndUpdateInfo(save,1); |
| | | } |
| | | return failNum; |
| | | } |
| | | |
| | | private TBillDto getTenentByBillId(String billId) { |
| | | return getBaseMapper().selectTenentByBillId(billId); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | TBill rentBill = new TBill(); |
| | | rentBill.setContractId(contract.getId()); |
| | | rentBill.setContractNumber(contract.getContractNumber()); |
| | | rentBill.setPayableFeesTime(firstPayTime); |
| | | rentBill.setPayableFeesTime(firstPayTime.toLocalDate()); |
| | | if (firstPayTime.toLocalDate().equals(LocalDate.now())){ |
| | | rentBill.setPayFeesStatus("1"); |
| | | }else { |
| | |
| | | depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney()); |
| | | depositBill.setStartTime(contract.getStartPayTime()); |
| | | depositBill.setEndTime(contract.getEndTime()); |
| | | depositBill.setPayableFeesTime(firstPayTime); |
| | | depositBill.setPayableFeesTime(firstPayTime.toLocalDate()); |
| | | if (firstPayTime.toLocalDate().equals(LocalDate.now())){ |
| | | depositBill.setPayFeesStatus("1"); |
| | | |
| | |
| | | } |
| | | tBill.setContractNumber(contract.getContractNumber()); |
| | | if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){ |
| | | tBill.setPayableFeesTime(contract.getEndTime()); |
| | | tBill.setPayableFeesTime(contract.getEndTime().toLocalDate()); |
| | | }else{ |
| | | tBill.setPayableFeesTime((contract.getPayType().equals("1")? |
| | | beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")? |
| | | beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12))); |
| | | beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")? |
| | | beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).toLocalDate())); |
| | | } |
| | | tBill.setPayFeesStatus("2"); |
| | | tBill.setBillType("1"); |
| | |
| | | } |
| | | tBill.setContractNumber(contract.getContractNumber()); |
| | | if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){ |
| | | tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0)); |
| | | tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0).toLocalDate()); |
| | | }else{ |
| | | tBill.setPayableFeesTime((contract.getPayType().equals("1")? |
| | | beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")? |
| | | beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0))); |
| | | beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15).toLocalDate():contract.getPayType().equals("2")? |
| | | beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15).toLocalDate():beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0).toLocalDate())); |
| | | } |
| | | tBill.setPayFeesStatus("1"); |
| | | tBill.setBillType("1"); |
| | |
| | | import com.ruoyi.system.query.TFlowManagementQuery; |
| | | import com.ruoyi.system.service.TFlowManagementService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.vo.TFlowManagementStatisticsVo; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | |
| | | ; |
| | | return this.baseMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | public TFlowManagementStatisticsVo getPaymentStats(TFlowManagementQuery query) { |
| | | return this.baseMapper.getPaymentStats(query); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.model.TInvoice; |
| | | import com.ruoyi.system.model.TInvoiceToBill; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.mapper.TInvoiceToBillMapper; |
| | | import com.ruoyi.system.model.TInvoiceToBill; |
| | | import com.ruoyi.system.query.TInvoiceToBillQuery; |
| | | import com.ruoyi.system.service.TInvoiceToBillService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | 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> |
New file |
| | |
| | | package com.ruoyi.system.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * @author 64502 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "系统流水统计VO") |
| | | public class TBankFlowStatisticsVo { |
| | | @ApiModelProperty(value = "流水总额") |
| | | private BigDecimal totalFlowMoney; |
| | | |
| | | @ApiModelProperty(value = "已抵扣金额") |
| | | private BigDecimal totalDeductionMoney; |
| | | |
| | | @ApiModelProperty(value = "剩余未抵扣") |
| | | private BigDecimal totalRemainingMoney; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.system.vo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * @author 64502 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "系统流水统计VO") |
| | | public class TFlowManagementStatisticsVo { |
| | | @ApiModelProperty(value = "系统流水总额") |
| | | private BigDecimal totalAmount; |
| | | |
| | | @ApiModelProperty(value = "微信") |
| | | private BigDecimal wechatAmount; |
| | | |
| | | @ApiModelProperty(value = "支付宝") |
| | | private BigDecimal alipayAmount; |
| | | |
| | | @ApiModelProperty(value = "线下支付") |
| | | private BigDecimal offlineAmount; |
| | | } |
| | |
| | | id, bank_serial_number, flow_money, deduction_money, remaining_money, pay_time, payer, flow_status, pay_type, payment_bill_id, create_time, update_time, create_by, update_by, disabled |
| | | </sql> |
| | | |
| | | |
| | | <!-- 定义结果映射 --> |
| | | <resultMap id="PaymentStatsResultMap" type="com.ruoyi.system.vo.TBankFlowStatisticsVo"> |
| | | <result property="totalFlowMoney" column="totalFlowMoney" /> |
| | | <result property="totalDeductionMoney" column="totalDeductionMoney" /> |
| | | <result property="totalRemainingMoney" column="totalRemainingMoney" /> |
| | | </resultMap> |
| | | |
| | | <!-- 统计总额和微信支付金额 --> |
| | | <select id="getPaymentStats" resultMap="PaymentStatsResultMap"> |
| | | SELECT |
| | | SUM(flow_money) AS totalFlowMoney, |
| | | SUM(deduction_money) AS totalDeductionMoney, |
| | | SUM(remaining_money) AS totalRemainingMoney |
| | | FROM |
| | | t_bank_flow |
| | | <where> |
| | | <if test="req.bankSerialNumber != null and req.bankSerialNumber != ''"> |
| | | and bank_serial_number = #{req.bankSerialNumber} |
| | | </if> |
| | | <if test="req.payer != null and req.payer != ''"> |
| | | and payer like concat('%', #{req.payer}, '%') |
| | | </if> |
| | | <if test="req.flowStatus != null and req.flowStatus != ''"> |
| | | and flow_status = #{req.flowStatus} |
| | | </if> |
| | | <if test="req.payStartTime != null and req.payStartTime != ''"> |
| | | and pay_time >= #{req.payStartTime} |
| | | </if> |
| | | <if test="req.payEndTime != null and req.payEndTime != ''"> |
| | | and pay_time <= #{req.payEndTime} |
| | | </if> |
| | | AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()} |
| | | </where> |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | and t.id = #{query.userId} |
| | | </if> |
| | | </where> |
| | | order by b.payable_fees_time desc |
| | | </select> |
| | | <select id="getBillList" resultType="com.ruoyi.system.dto.TBillDto"> |
| | | SELECT |
| | |
| | | </where> |
| | | order by b.pay_fees_time |
| | | </select> |
| | | |
| | | <select id="selectTenentByBillId" resultType="com.ruoyi.system.dto.TBillDto"> |
| | | SELECT |
| | | b.*, |
| | | t.resident_name as residentName, |
| | | t.email, |
| | | t.phone, |
| | | t.account, |
| | | h.house_name as houseName |
| | | FROM |
| | | t_bill b |
| | | 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.id = #{billId} |
| | | </select> |
| | | </mapper> |
| | |
| | | id, sys_serial_number, bank_serial_number, flow_money, deduction_money, remaining_money, pay_time, payer, flow_status, flow_type, pay_type, payment_bill_id, create_time, update_time, create_by, update_by, disabled |
| | | </sql> |
| | | |
| | | |
| | | <!-- 定义结果映射 --> |
| | | <resultMap id="PaymentStatsResultMap" type="com.ruoyi.system.vo.TFlowManagementStatisticsVo"> |
| | | <result property="totalAmount" column="total_amount" /> |
| | | <result property="wechatAmount" column="wechat_amount" /> |
| | | <result property="alipayAmount" column="alipay_amount" /> |
| | | <result property="offlineAmount" column="offline_amount" /> |
| | | </resultMap> |
| | | |
| | | <!-- 统计总额和微信支付金额 --> |
| | | <select id="getPaymentStats" resultMap="PaymentStatsResultMap"> |
| | | SELECT SUM(flow_money) AS total_amount, |
| | | SUM(CASE WHEN pay_type = 1 THEN flow_money ELSE 0 END ) AS wechat_amount, |
| | | SUM(CASE WHEN pay_type = 2 THEN flow_money ELSE 0 END ) AS alipay_amount, |
| | | SUM(CASE WHEN pay_type = 3 THEN flow_money ELSE 0 END ) AS offline_amount |
| | | FROM |
| | | t_flow_management |
| | | <where> |
| | | <if test="req.sysSerialNumber != null and req.sysSerialNumber != ''"> |
| | | and sys_serial_number = #{req.sysSerialNumber} |
| | | </if> |
| | | <if test="req.bankSerialNumber != null and req.bankSerialNumber != ''"> |
| | | and bank_serial_number = #{req.bankSerialNumber} |
| | | </if> |
| | | <if test="req.payer != null and req.payer != ''"> |
| | | and payer like concat('%', #{req.payer}, '%') |
| | | </if> |
| | | <if test="req.payType != null and req.payType != ''"> |
| | | and pay_type = #{req.payType} |
| | | </if> |
| | | <if test="req.payStartTime != null and req.payStartTime != ''"> |
| | | and pay_time >= #{req.payStartTime} |
| | | </if> |
| | | <if test="req.payEndTime != null and req.payEndTime != ''"> |
| | | and pay_time <= #{req.payEndTime} |
| | | </if> |
| | | AND disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()} |
| | | </where> |
| | | </select> |
| | | |
| | | |
| | | |
| | | </mapper> |