浏览代码

Merge remote-tracking branch 'origin/master'

sola 4 月之前
父节点
当前提交
7a197aba88
共有 22 个文件被更改,包括 1052 次插入409 次删除
  1. 19 0
      zhsw-common/src/main/java/com/rongwei/zhsw/system/dao/SwPrintRepairConfigDao.java
  2. 130 68
      zhsw-common/src/main/java/com/rongwei/zhsw/system/importListener/MeterReadingRecordListener.java
  3. 1 1
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/SwRefundRequestRecordService.java
  4. 59 50
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/BillGenerationServiceImpl.java
  5. 30 16
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/ImportExcelServiceImpl.java
  6. 125 26
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/PrintServiceImpl.java
  7. 2 1
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwBillManagementUnpaidServiceImpl.java
  8. 216 111
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwBillingRecordServiceImpl.java
  9. 103 50
      zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwRefundRequestRecordServiceImpl.java
  10. 155 0
      zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/NumberToChineseUppercaseUtils.java
  11. 1 1
      zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/ZHSWCommonUtils.java
  12. 33 2
      zhsw-common/src/main/java/com/rongwei/zhsw/system/wechat/impl/AccountServiceImpl.java
  13. 1 1
      zhsw-common/src/main/java/com/rongwei/zhsw/system/wechat/impl/RegistrationServiceImpl.java
  14. 2 0
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwBillManagementPaidDo.java
  15. 46 46
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwBillingRecordDo.java
  16. 77 0
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwPrintRepairConfigDo.java
  17. 3 1
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwUserManagementDo.java
  18. 1 1
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwUserWechatDo.java
  19. 2 0
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/dto/PaymentRequestDTO.java
  20. 20 34
      zhsw-entity/src/main/java/com/rongwe/zhsw/system/vo/PrintReceiptVo.java
  21. 25 0
      zhsw-server/src/main/java/com/rongwei/zhsw/system/controller/SwRefundRequestRecordController.java
  22. 1 0
      zhsw-server/src/main/resources/bootstrap-dev.yml

+ 19 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/dao/SwPrintRepairConfigDao.java

@@ -0,0 +1,19 @@
+package com.rongwei.zhsw.system.dao;
+
+import com.rongwe.zhsw.system.domain.SwPrintRepairConfigDo;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author libai
+* @description 针对表【sw_print_repair_config(票据打印配置信息)】的数据库操作Mapper
+* @createDate 2025-03-21 13:18:58
+* @Entity generator.domain.SwPrintRepairConfig
+*/
+public interface SwPrintRepairConfigDao extends BaseMapper<SwPrintRepairConfigDo> {
+
+}
+
+
+
+

+ 130 - 68
zhsw-common/src/main/java/com/rongwei/zhsw/system/importListener/MeterReadingRecordListener.java

@@ -15,13 +15,15 @@ import com.rongwei.zhsw.system.service.impl.SwUserManagementServiceImpl;
 import com.rongwei.zhsw.system.service.impl.SwWaterUsageEntryServiceImpl;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.poi.ss.formula.functions.T;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.rongwei.zhsw.system.utils.ZHSWCommonUtils.getCurrentUser;
@@ -34,105 +36,165 @@ import static com.rongwei.zhsw.system.utils.ZHSWCommonUtils.getCurrentUser;
  */
 public class MeterReadingRecordListener extends AnalysisEventListener<ImportMeterReadingRecordVo> {
     private static final Logger log = LoggerFactory.getLogger(MeterReadingRecordListener.class);
-    private  ThreadLocal<List<ImportMeterReadingRecordVo>> recordList = ThreadLocal.withInitial(ArrayList::new);
-    private  ThreadLocal<List<SwWaterUsageEntryDo>> saveList = ThreadLocal.withInitial(ArrayList::new);
+    private List<ImportMeterReadingRecordVo> recordList = new ArrayList<>();
+    private List<SwWaterUsageEntryDo> saveList = new ArrayList<>();
     private SwUserManagementServiceImpl swUserManagementService;
     private SwWaterUsageEntryServiceImpl swWaterUsageEntryService;
+    private Date nowDate;
 
-    public MeterReadingRecordListener(SwUserManagementServiceImpl userManagementService,SwWaterUsageEntryServiceImpl waterUsageEntryService) {
+    // 出现重复记录的数据
+    private List<ImportMeterReadingRecordVo> duplicateRecordList = new ArrayList<>();
+    // 时间异常的记录
+    private List<ImportMeterReadingRecordVo> timeAnomalyList = new ArrayList<>();
+
+
+    public MeterReadingRecordListener(SwUserManagementServiceImpl userManagementService, SwWaterUsageEntryServiceImpl waterUsageEntryService) {
         this.swUserManagementService = userManagementService;
         this.swWaterUsageEntryService = waterUsageEntryService;
+        this.nowDate = new Date();
     }
 
+    /**
+     * 导入前数据校验
+     *
+     * @param importMeterReadingRecordVo
+     * @param analysisContext
+     */
     @Override
     public void invoke(ImportMeterReadingRecordVo importMeterReadingRecordVo, AnalysisContext analysisContext) {
-
         if (StringUtils.isBlank(importMeterReadingRecordVo.getAccountNumber())) {
             throw new CustomException("户号为空");
         }
         if (importMeterReadingRecordVo.getReadingDate() == null) {
             throw new CustomException("抄表日期");
         }
-        if (importMeterReadingRecordVo.getConsumption() == null) {
-            throw new CustomException("读数为空");
+        if (importMeterReadingRecordVo.getConsumption() == null && importMeterReadingRecordVo.getConsumption().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new CustomException("读数为空,抄表数小于0");
         }
-        // 校验户号是否能重复
-
-
-        // 校验当前睡觉是否存在抄表记录
-        int count = swWaterUsageEntryService.count(new LambdaQueryWrapper<SwWaterUsageEntryDo>()
-                .eq(BaseDo::getDeleted, "0")
-                .eq(SwWaterUsageEntryDo::getUsernumber, importMeterReadingRecordVo.getAccountNumber())
-                .ge(SwWaterUsageEntryDo::getCurrentreadingdate, importMeterReadingRecordVo.getReadingDate()));
-        if(count==0) {
-            recordList.get().add(importMeterReadingRecordVo);
+        // 判断数据是否重复
+        boolean b = recordList.stream().anyMatch(record -> record.getAccountNumber().equals(importMeterReadingRecordVo.getAccountNumber())
+                && record.getReadingDate().equals(importMeterReadingRecordVo.getReadingDate())
+        );
+        if (b) {
+            duplicateRecordList.add(importMeterReadingRecordVo);
+            return;
         }
+        // 判断抄表日期和当前日期的关系
+        if (importMeterReadingRecordVo.getReadingDate().compareTo(nowDate) > 0) {
+            timeAnomalyList.add(importMeterReadingRecordVo);
+            return;
+        }
+        /**
+         * 校验导入的日期和当前日期的关系
+         */
+        recordList.add(importMeterReadingRecordVo);
     }
 
     @Override
     public void doAfterAllAnalysed(AnalysisContext analysisContext) {
-        if(recordList.get().isEmpty()){
+        if (recordList.isEmpty()) {
             return;
         }
-        List<String> accountNumList = recordList.get().stream().map(ImportMeterReadingRecordVo::getAccountNumber).distinct().collect(Collectors.toList());
+        if (!duplicateRecordList.isEmpty()) {
+            throw new CustomException(
+                    "Excel表中" +
+                            duplicateRecordList.stream().map(ImportMeterReadingRecordVo::getAccountNumber).collect(Collectors.joining("、"))
+                            + "户号存在相同抄表日期记录,请检查!");
+        }
+        if (!timeAnomalyList.isEmpty()) {
+            throw new CustomException(
+                    "Excel表中" +
+                            timeAnomalyList.stream().map(ImportMeterReadingRecordVo::getAccountNumber).collect(Collectors.joining("、"))
+                            + "户号存在抄表日期大于当前日期的记录,请检查!");
+        }
+
+
+        // 获取数据中的所有户号
+        List<String> accountNumList = recordList.stream().map(ImportMeterReadingRecordVo::getAccountNumber).distinct().collect(Collectors.toList());
+
         List<SwUserManagementDo> allAccountData = new ArrayList<>();
-        Lists.partition(accountNumList,5000).forEach(accountNum -> {
+        // 获取户号信息
+        Lists.partition(accountNumList, 5000).parallelStream().forEach(accountNum -> {
             allAccountData.addAll(swUserManagementService.list(new LambdaQueryWrapper<SwUserManagementDo>()
                     .eq(BaseDo::getDeleted, "0")
                     .in(SwUserManagementDo::getUsernumber, accountNumList)));
         });
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+        // 校验导入的时间是否小于对应户号的最大抄表日期
+        String errorStrDesc = recordList.parallelStream()
+                .filter(record ->
+                        allAccountData.parallelStream().anyMatch(userAccount -> userAccount.getUsernumber()
+                                .equals(record.getAccountNumber()) &&
+                                (userAccount.getLastmeterreaddate() != null && userAccount.getLastmeterreaddate().compareTo(record.getReadingDate()) >= 0))
+                ).map(info -> info.getAccountNumber() + '-' + sdf.format(info.getReadingDate()))
+                .collect(Collectors.joining(" "));
+        if (StringUtils.isNotBlank(errorStrDesc)) {
+            throw new CustomException(
+                    "Excel表中" +
+                            errorStrDesc
+                            + "记录日期小于对应用户最近抄表日期,请检查!");
+        }
+        // 按照户号分组 减少遍历时间
+        Map<String, SwUserManagementDo> userMap = allAccountData.stream().collect(Collectors.groupingBy(SwUserManagementDo::getUsernumber,
+        Collectors.reducing(
+                null, // 初始值(可能为 null)
+                (a, b) -> a != null ? a : b // 合并规则:保留第一个非 null 元素
+        )));
+
+        // 当前导入用户的操作人
         SysUserVo currentUser = getCurrentUser();
         Calendar calendar = Calendar.getInstance();
-        recordList.get().forEach(record->{
-            SwUserManagementDo swUserManagementDo = allAccountData.stream().filter(accountInfo -> accountInfo.getUsernumber().equals(record.getAccountNumber()))
-                    .findFirst()
-                    .orElse(null);
-            SwWaterUsageEntryDo swWaterUsageEntryDo = new SwWaterUsageEntryDo();
-            if(swUserManagementDo!=null){
-                // 如果时间一致不让当如
-                if(record.getReadingDate().equals(swUserManagementDo.getLastmeterreaddate())){
-                    log.error("本次抄表日期和最后一次抄表日期一致");
-                    return;
+        /**********数据解析开始************/
+        recordList = recordList.stream().sorted(Comparator.comparing(ImportMeterReadingRecordVo::getReadingDate)).collect(Collectors.toList());
+        // 解决同一个excel中出现多次相同的户号数据 要记录上次读数的问题 对数据按照户号分组
+        Map<String, List<ImportMeterReadingRecordVo>> collect = recordList.stream()
+                .collect(Collectors.groupingBy(ImportMeterReadingRecordVo::getAccountNumber, Collectors.toList()));
+
+        collect.forEach((accountNum, v) -> {
+            SwUserManagementDo swUserManagementDo = userMap.getOrDefault(accountNum,null);
+            SwWaterUsageEntryDo waterUsageEntryDo;
+            // 循环数据
+            SwUserManagementDo saveUserDo;
+            for (int i = 0; i < v.size(); i++) {
+                ImportMeterReadingRecordVo importMeterReadingRecordVo = v.get(i);
+                calendar.setTime(importMeterReadingRecordVo.getReadingDate());
+                waterUsageEntryDo = new SwWaterUsageEntryDo();
+                waterUsageEntryDo.setId(SecurityUtil.getUUID());
+                waterUsageEntryDo.setUsernumber(accountNum);
+                waterUsageEntryDo.setThisreading(importMeterReadingRecordVo.getConsumption());
+                waterUsageEntryDo.setCurrentreadingdate(importMeterReadingRecordVo.getReadingDate());
+                waterUsageEntryDo.setReadingsource("1");
+                // 当前户号在系统中不存在
+                if (swUserManagementDo == null) {
+                    // 户号不存在
+                    waterUsageEntryDo.setState(2);
+                } else {
+                    // 增加用户信息
+                    waterUsageEntryDo.setAddress(swUserManagementDo.getAddress());
+                    waterUsageEntryDo.setUsername(swUserManagementDo.getUsername());
+                    waterUsageEntryDo.setUserid(swUserManagementDo.getId());
+                    waterUsageEntryDo.setState(0);
+                    waterUsageEntryDo.setLastreading(swUserManagementDo.getLastmeterreading());
+                    waterUsageEntryDo.setLastreadingdate(swUserManagementDo.getLastmeterreaddate());
+                    waterUsageEntryDo.setCommunityname(swUserManagementDo.getVillagename());
+                    waterUsageEntryDo.setCommunitycode(swUserManagementDo.getVolumeno());
+                    // 修改用户表的最后一次 抄表日期和抄表度数
+                    swUserManagementDo.setLastmeterreading(importMeterReadingRecordVo.getConsumption());
+                    swUserManagementDo.setLastmeterreaddate(importMeterReadingRecordVo.getReadingDate());
                 }
-                swWaterUsageEntryDo.setAddress(swUserManagementDo.getAddress());
-                swWaterUsageEntryDo.setUsername(swUserManagementDo.getUsername());
-                swWaterUsageEntryDo.setUserid(swUserManagementDo.getId());
-                swWaterUsageEntryDo.setState(0);
-                swWaterUsageEntryDo.setLastreading(swUserManagementDo.getLastmeterreading());
-                swWaterUsageEntryDo.setLastreadingdate(swUserManagementDo.getLastmeterreaddate());
-                swWaterUsageEntryDo.setCommunityname(swUserManagementDo.getVillagename());
-                swWaterUsageEntryDo.setCommunitycode(swUserManagementDo.getVolumeno());
-            }else{
-                swWaterUsageEntryDo.setState(2);
+                waterUsageEntryDo.setYear(calendar.get(Calendar.YEAR));
+                waterUsageEntryDo.setMonth(calendar.get(Calendar.MONTH) + 1);
+                waterUsageEntryDo.setIsds(String.valueOf(0));
+                ZHSWCommonUtils.initModelGeneralParameters(waterUsageEntryDo, currentUser);
+                saveList.add(waterUsageEntryDo);
             }
-            calendar.setTime(record.getReadingDate());
-            swWaterUsageEntryDo.setId(SecurityUtil.getUUID());
-            swWaterUsageEntryDo.setUsernumber(record.getAccountNumber());
-            swWaterUsageEntryDo.setThisreading(record.getConsumption());
-
-            swWaterUsageEntryDo.setCurrentreadingdate(record.getReadingDate());
-            swWaterUsageEntryDo.setReadingsource("1");
-
-            swWaterUsageEntryDo.setYear(calendar.get(Calendar.YEAR));
-            swWaterUsageEntryDo.setMonth(calendar.get(Calendar.MONTH)+1);
-            swWaterUsageEntryDo.setIsds(String.valueOf(0));
-            ZHSWCommonUtils.initModelGeneralParameters(swWaterUsageEntryDo,currentUser);
-            saveList.get().add(swWaterUsageEntryDo);
         });
-        save(saveList.get());
-
-        recordList.remove();
-    }
-    @Transactional
-    public void save(List<SwWaterUsageEntryDo> saveList){
-        if(!saveList.isEmpty()){
-            swWaterUsageEntryService.saveBatch(saveList,500);
-        }
     }
 
-    public List<SwWaterUsageEntryDo> getDatas() {
-        List<SwWaterUsageEntryDo> swWaterUsageEntryDos = saveList.get();
-        saveList.remove();
-        return swWaterUsageEntryDos;
+
+
+    public List<SwWaterUsageEntryDo> getData() {
+        return saveList;
     }
 }

+ 1 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/SwRefundRequestRecordService.java

@@ -15,5 +15,5 @@ import com.rongwei.rwcommon.base.R;
 public interface SwRefundRequestRecordService  extends IService<SwRefundRequestRecordDO> {
 
 
-    R refundApplication( String id);
+    R refundApplication( String id) throws Exception;
 }

+ 59 - 50
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/BillGenerationServiceImpl.java

@@ -5,7 +5,6 @@ import com.rongwe.zhsw.system.domain.SwBillManagementUnpaidDo;
 import com.rongwe.zhsw.system.domain.SwUserManagementDo;
 import com.rongwe.zhsw.system.domain.SwWaterUsageEntryDo;
 import com.rongwei.rwcommon.base.BaseDo;
-import com.rongwei.rwcommon.base.exception.CustomException;
 import com.rongwei.rwcommon.utils.SecurityUtil;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
 import org.slf4j.Logger;
@@ -16,7 +15,6 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.DefaultTransactionDefinition;
 
 import java.math.BigDecimal;
@@ -25,8 +23,6 @@ import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static org.springframework.transaction.annotation.Propagation.REQUIRED;
-
 /**
  * BillGenerationServiceImpl class
  *
@@ -46,14 +42,14 @@ public class BillGenerationServiceImpl {
     @Autowired
     private DataSourceTransactionManager transactionManager;
 
-    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+    private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
 
     public static String formatDate(Date date) {
         synchronized (formatter) {
             return formatter.format(date);
         }
     }
-    @Async(value = "customThreadPool")
+
     public void generateBill(List<SwWaterUsageEntryDo> swWaterUsageEntryDoList) {
         log.info("开始生成账单信息");
         if (swWaterUsageEntryDoList == null || swWaterUsageEntryDoList.isEmpty()) {
@@ -71,37 +67,40 @@ public class BillGenerationServiceImpl {
         /*******当前账单的所有户号******/
         List<String> accountNumberList = collect.stream().map(SwWaterUsageEntryDo::getUsernumber).collect(Collectors.toList());
         /*******当前账单的所有户号******/
-        List<SwUserManagementDo> swUserManagementList = swUserManagementService.list(new LambdaQueryWrapper<SwUserManagementDo>()
-                .select(SwUserManagementDo::getId,
-                        SwUserManagementDo::getUsernumber,
-                        SwUserManagementDo::getMetermaxvalue,
-                        SwUserManagementDo::getWaterprice,
-                        SwUserManagementDo::getVillagename,
-                        SwUserManagementDo::getUsernumber,
-                        SwUserManagementDo::getUsername,
-                        SwUserManagementDo::getUsertype,
-                        SwUserManagementDo::getAddress,
-                        SwUserManagementDo::getExemptionamount,
-                        SwUserManagementDo::getExemptionwater,
-                        SwUserManagementDo::getWatertype,
-                        SwUserManagementDo::getLastmeterreaddate,
-                        SwUserManagementDo::getLastmeterreading
-                )
-                .eq(BaseDo::getDeleted, "0")
-                .in(SwUserManagementDo::getUsernumber, accountNumberList));
+        Map<String, SwUserManagementDo> userMap = swUserManagementService.list(new LambdaQueryWrapper<SwUserManagementDo>()
+                        .select(SwUserManagementDo::getId,
+                                SwUserManagementDo::getUsernumber,
+                                SwUserManagementDo::getMetermaxvalue,
+                                SwUserManagementDo::getWaterprice,
+                                SwUserManagementDo::getVillagename,
+                                SwUserManagementDo::getUsernumber,
+                                SwUserManagementDo::getUsername,
+                                SwUserManagementDo::getUsertype,
+                                SwUserManagementDo::getAddress,
+                                SwUserManagementDo::getExemptionamount,
+                                SwUserManagementDo::getExemptionwater,
+                                SwUserManagementDo::getWatertype,
+                                SwUserManagementDo::getLastmeterreaddate,
+                                SwUserManagementDo::getLastmeterreading
+                        )
+                        .eq(BaseDo::getDeleted, "0")
+                        .in(SwUserManagementDo::getUsernumber, accountNumberList))
+                .stream().collect(Collectors.groupingBy(SwUserManagementDo::getUsernumber,
+                        Collectors.reducing(
+                                null, // 初始值(可能为 null)
+                                (a, b) -> a != null ? a : b // 合并规则:保留第一个非 null 元素
+                        )));
 
         collect.forEach(swWaterUsageEntry -> {
             String usernumber = swWaterUsageEntry.getUsernumber();
             // 本次抄表日期
             Date currentreadingdate = swWaterUsageEntry.getCurrentreadingdate();
             // 校验 是否已存在抄表记录
-            if (swWaterUsageEntry.getState() != 0) {
+            if (swWaterUsageEntry.getState() == 1) {
                 log.error("当前用户:{},时间:{}的抄表记录已生成账单信息", usernumber, currentreadingdate);
                 return;
             }
-            SwUserManagementDo swUserManagementDo = swUserManagementList.stream().filter(data -> data.getUsernumber().equals(swWaterUsageEntry.getUsernumber()))
-                    .findFirst()
-                    .orElse(null);
+            SwUserManagementDo swUserManagementDo = userMap.getOrDefault(swWaterUsageEntry.getUsernumber(), null);
 
             SwWaterUsageEntryDo usageEntryDo = new SwWaterUsageEntryDo();
             usageEntryDo.setId(swWaterUsageEntry.getId());
@@ -110,10 +109,7 @@ public class BillGenerationServiceImpl {
                 usageEntryDo.setState(2);
                 saveUsageEntryList.add(usageEntryDo);
                 return;
-            }else{
-
             }
-
             // 校验是否可以生成账单
             if (swUserManagementDo.getLastmeterreaddate() != null &&
                     swUserManagementDo.getLastmeterreaddate().compareTo(swWaterUsageEntry.getCurrentreadingdate()) > 0) {
@@ -122,17 +118,18 @@ public class BillGenerationServiceImpl {
                 saveUsageEntryList.add(usageEntryDo);
                 return;
             }
-            SwBillManagementUnpaidDo swBillManagementUnpaidDo=null;
+            SwBillManagementUnpaidDo swBillManagementUnpaidDo = null;
             try {
                 // 生成代缴费账单
-                swBillManagementUnpaidDo= produceBill(swUserManagementDo, swWaterUsageEntry);
-            }catch (Exception e) {
-                log.error("缴费记录生成失败原因:{}",e.getMessage());
+                swBillManagementUnpaidDo = produceBill(swUserManagementDo, swWaterUsageEntry);
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error("缴费记录生成失败原因:{}", e.getMessage());
             }
 
-            if(swBillManagementUnpaidDo==null){
+            if (swBillManagementUnpaidDo == null) {
                 usageEntryDo.setState(4);
-            }else{
+            } else {
                 usageEntryDo.setState(1);
                 saveList.add(swBillManagementUnpaidDo);
                 // 设置本次的抄表日期
@@ -143,15 +140,16 @@ public class BillGenerationServiceImpl {
             userSaveList.add(swUserManagementDo);
             saveUsageEntryList.add(usageEntryDo);
         });
-        dataSave(saveList, userSaveList, saveUsageEntryList);
+        dataSave(saveList, saveUsageEntryList, userSaveList);
     }
 
-
+    @Async(value = "customThreadPool")
     public void generateBill(String id) {
         SwWaterUsageEntryDo swWaterUsageEntryDo = swWaterUsageEntryService.getById(id);
         this.generateBill(Collections.singletonList(swWaterUsageEntryDo));
     }
 
+    @Async(value = "customThreadPool")
     public void generateBill(List<String> ids, boolean a) {
         if (ids.isEmpty()) {
             log.error("抄表记录ID为空");
@@ -160,6 +158,7 @@ public class BillGenerationServiceImpl {
         this.generateBill(swWaterUsageEntryService.getBaseMapper().selectBatchIds(ids));
     }
 
+    @Async(value = "customThreadPool")
     public void generateBill() {
         List<SwWaterUsageEntryDo> list = swWaterUsageEntryService.list(new LambdaQueryWrapper<SwWaterUsageEntryDo>()
                 .eq(SwWaterUsageEntryDo::getDeleted, "0")
@@ -169,26 +168,35 @@ public class BillGenerationServiceImpl {
 
     /**
      * 数据保存
+     *
      * @param swBillManagementUnpaidDos 账单信息
-     * @param userSaveList  用户信息
-     * @param saveUsageEntryList 抄表记录
+     * @param userSaveList              用户信息
+     * @param saveUsageEntryList        抄表记录
      */
 
-    public void dataSave(List<SwBillManagementUnpaidDo> swBillManagementUnpaidDos, List<SwUserManagementDo> userSaveList,
-                         List<SwWaterUsageEntryDo> saveUsageEntryList) {
+    public void dataSave(List<SwBillManagementUnpaidDo> swBillManagementUnpaidDos,
+                         List<SwWaterUsageEntryDo> saveUsageEntryList, List<SwUserManagementDo> userSaveList) {
         DefaultTransactionDefinition def = new DefaultTransactionDefinition();
         def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
         TransactionStatus status = transactionManager.getTransaction(def);
         try {
-            // 抄表记录状态更新
-            swWaterUsageEntryService.updateBatchById(saveUsageEntryList,4000);
-            // 账单保存
-            swBillManagementUnpaidService.saveBatch(swBillManagementUnpaidDos, 1000);
-            // 更新用户表的本次抄表时间和本次抄表度数
-            swUserManagementService.updateBatchById(userSaveList);
+            if (!saveUsageEntryList.isEmpty()) {
+                // 抄表记录状态更新
+                swWaterUsageEntryService.updateBatchById(saveUsageEntryList, 4000);
+            }
+            if (!swBillManagementUnpaidDos.isEmpty()) {
+                // 账单保存
+                swBillManagementUnpaidService.saveBatch(swBillManagementUnpaidDos, 1000);
+            }
+            if (!userSaveList.isEmpty()) {
+                // 更新用户表的本次抄表时间和本次抄表度数
+                swUserManagementService.updateBatchById(userSaveList);
+            }
+
             // 事务性操作
             transactionManager.commit(status);
         } catch (Exception e) {
+            e.printStackTrace();
             transactionManager.rollback(status);
             log.error("账单保存异常");
         }
@@ -252,7 +260,8 @@ public class BillGenerationServiceImpl {
         swBillManagementUnpaidDo.setOughttohavepaid(waterprice.multiply(waterConsumption));
         swBillManagementUnpaidDo.setWatertype(swUserManagementDo.getWatertype());
         // 实际应缴=原应缴-减免
-        swBillManagementUnpaidDo.setActualdue(swBillManagementUnpaidDo.getOughttohavepaid().subtract(swBillManagementUnpaidDo.getFeewaiver()));
+        BigDecimal subtract = swBillManagementUnpaidDo.getOughttohavepaid().subtract(swBillManagementUnpaidDo.getFeewaiver());
+        swBillManagementUnpaidDo.setActualdue(subtract.compareTo(BigDecimal.ZERO) > 0 ? subtract : BigDecimal.ZERO);
         swBillManagementUnpaidDo.setLastmeterreadingdate(swWaterUsageEntryDo.getLastreadingdate());
         swBillManagementUnpaidDo.setLastmeterreading(swWaterUsageEntryDo.getLastreading());
         swBillManagementUnpaidDo.setThismeterreadingdate(swWaterUsageEntryDo.getCurrentreadingdate());

+ 30 - 16
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/ImportExcelServiceImpl.java

@@ -1,30 +1,25 @@
 package com.rongwei.zhsw.system.service.impl;
 
 import com.alibaba.excel.EasyExcel;
+import com.rongwe.zhsw.system.domain.SwUserManagementDo;
 import com.rongwe.zhsw.system.domain.SwWaterUsageEntryDo;
 import com.rongwe.zhsw.system.vo.ImportMeterReadingRecordVo;
 import com.rongwei.rwcommon.base.R;
-import com.rongwei.rwcommon.base.exception.CustomException;
 import com.rongwei.rwcommoncomponent.file.dao.SysFileItemDao;
 import com.rongwei.rwcommonentity.commonservers.domain.SysFileItemDo;
 import com.rongwei.zhsw.system.importListener.MeterReadingRecordListener;
 import com.rongwei.zhsw.system.service.ImportExcelService;
 import org.apache.commons.lang.StringUtils;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
-import org.apache.poi.xssf.eventusermodel.XSSFReader;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.xml.sax.InputSource;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.helpers.XMLReaderFactory;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.io.File;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import static com.rongwei.rwcommon.utils.UtilsChecks.parameterCheck;
@@ -45,23 +40,42 @@ public class ImportExcelServiceImpl implements ImportExcelService {
     private SwWaterUsageEntryServiceImpl waterUsageEntryService;
     @Autowired
     private BillGenerationServiceImpl billGenerationService;
+    private static final Logger log = LoggerFactory.getLogger(ImportExcelServiceImpl.class);
     /**
      * 抄表记录生成
+     *
      * @param fileId
      * @return
      */
     @Override
     public R meterReadingRecord(String fileId) {
         File file = readFile(fileId);
+        // 数据读取
+        long startTime = System.currentTimeMillis();
         MeterReadingRecordListener meterReadingRecordListener = new MeterReadingRecordListener(userManagementService, waterUsageEntryService);
-        EasyExcel.read(file, ImportMeterReadingRecordVo.class,meterReadingRecordListener).sheet().doRead();
-        List<SwWaterUsageEntryDo> datas = meterReadingRecordListener.getDatas();
-
-        List<String> ids = datas.stream().map(SwWaterUsageEntryDo::getId).distinct().collect(Collectors.toList());
-        billGenerationService.generateBill(ids,true);
+        EasyExcel.read(file, ImportMeterReadingRecordVo.class, meterReadingRecordListener).sheet().doRead();
+        // 获取处理之后的数据
+        long entTime = System.currentTimeMillis();
+        log.error("excel解析时长:{}",startTime-entTime);
+         startTime = System.currentTimeMillis();
+        List<SwWaterUsageEntryDo> saveList =  meterReadingRecordListener.getData();
+        this.save(saveList);
+        entTime = System.currentTimeMillis();
+        log.error("数据保存时长:{}",startTime-entTime);
+        List<String> ids = saveList.stream().map(SwWaterUsageEntryDo::getId).distinct().collect(Collectors.toList());
+        startTime = System.currentTimeMillis();
+        billGenerationService.generateBill(ids, true);
+        entTime = System.currentTimeMillis();
+        log.error("账单生成时长:{}",startTime-entTime);
         return R.ok();
     }
 
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public void save(List<SwWaterUsageEntryDo> datas) {
+        waterUsageEntryService.saveBatch(datas, 1000);
+    }
+
+
     public File readFile(String fileId) {
         parameterCheck(() -> StringUtils.isBlank(fileId), "请上传文件", "文件ID为空");
         SysFileItemDo fileItemDo = sysFileItemDao.selectById(fileId);

+ 125 - 26
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/PrintServiceImpl.java

@@ -1,14 +1,22 @@
 package com.rongwei.zhsw.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.collect.Lists;
 import com.rongwe.zhsw.system.domain.SwBillManagementPaidDo;
 import com.rongwe.zhsw.system.domain.SwBillingRecordDo;
+import com.rongwe.zhsw.system.domain.SwPrintRepairConfigDo;
 import com.rongwe.zhsw.system.domain.SwUserManagementDo;
 import com.rongwe.zhsw.system.vo.PrintReceiptVo;
+import com.rongwei.rwadmincommon.system.dao.SysDictDao;
+import com.rongwei.rwadmincommon.system.domain.SysDictDo;
+import com.rongwei.rwadmincommon.system.vo.SysUserVo;
 import com.rongwei.rwcommon.base.BaseDo;
 import com.rongwei.rwcommon.base.R;
 import com.rongwei.rwcommon.base.exception.CustomException;
+import com.rongwei.zhsw.system.dao.SwPrintRepairConfigDao;
 import com.rongwei.zhsw.system.service.PrintService;
+import com.rongwei.zhsw.system.utils.NumberToChineseUppercaseUtils;
+import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -22,6 +30,7 @@ import java.util.stream.Collectors;
 
 import static com.rongwei.zhsw.system.utils.SaveConstans.billReccord.FULLREFUNDSTATUS;
 
+
 /**
  * PrintServiceImpl class
  *
@@ -37,6 +46,11 @@ public class PrintServiceImpl implements PrintService {
     private SwUserManagementServiceImpl swUserManagementService;
     @Autowired
     private SwBillManagementPaidServiceImpl swBillManagementPaidService;
+    @Autowired
+    private SwPrintRepairConfigDao swPrintRepairConfigDao;
+    @Autowired
+    private SysDictDao sysDictDao;
+
 
     @Override
     public R printReceipt(List<String> ids) {
@@ -51,6 +65,8 @@ public class PrintServiceImpl implements PrintService {
         if (b) {
             throw new CustomException("存在全额退款记录,不可打印票据");
         }
+
+
         // 户号
         List<String> accountList = swBillingRecordDos.stream().map(SwBillingRecordDo::getUsernumber).collect(Collectors.toList());
         // 用户信息
@@ -62,21 +78,25 @@ public class PrintServiceImpl implements PrintService {
                 .eq(SwBillManagementPaidDo::getDeleted, "0")
                 .in(SwBillManagementPaidDo::getUsernumber, accountList)
                 .in(SwBillManagementPaidDo::getPaymentrecordid, ids));
-        List<PrintReceiptVo> receiptVoList = new ArrayList<>();
+
         Date date = new Date();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         String dateStr = sdf.format(date);
         // 生成票据导出所需要的数据
-        PrintReceiptVo printReceiptVo;
         // 用户信息
         SwUserManagementDo swUserManagementDo;
-        // 用水信息
-        PrintReceiptVo.WaterUsageInfo waterUsageInfo;
+
+        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
 
         // 账单信息
         List<SwBillManagementPaidDo> swBillManagementPaidDoList;
+        List<List<Object>> datas = new ArrayList<>();
+        /****************************数据组装开始******************************************/
+        List<SysDictDo> sysDictDoList = sysDictDao.selectList(new LambdaQueryWrapper<SysDictDo>()
+                .eq(BaseDo::getDeleted, "0")
+                .eq(SysDictDo::getDicttype, "water-use-type"));
         for (SwBillingRecordDo swBillingRecordDo : swBillingRecordDos) {
-            printReceiptVo = new PrintReceiptVo();
+            List<Object> listData = new ArrayList<>();
             swUserManagementDo = swUserManagementDos.stream()
                     .filter(data -> data.getUsernumber().equals(swBillingRecordDo.getUsernumber()))
                     .findFirst()
@@ -85,34 +105,113 @@ public class PrintServiceImpl implements PrintService {
                 log.error("户号:{}不存在", swBillingRecordDo.getUsernumber());
                 throw new CustomException("以下户号: " + swBillingRecordDo.getUsernumber() + "不存在");
             }
-            printReceiptVo.setPrintDateStr(dateStr);
-            printReceiptVo.setAccount(swUserManagementDo.getUsernumber());
-            printReceiptVo.setName(swUserManagementDo.getUsername());
-            printReceiptVo.setUserType(swUserManagementDo.getUsertype());
-            printReceiptVo.setAddress(swUserManagementDo.getAddress());
-            printReceiptVo.setBalance(swUserManagementDo.getAccountbalance().stripTrailingZeros());
+            listData.add(dateStr);
+            listData.add(swUserManagementDo.getUsernumber());
+            listData.add(swUserManagementDo.getAccountbalance().stripTrailingZeros());
+            String usertype = swUserManagementDo.getUsertype();
+            SysDictDo sysDictDo = sysDictDoList.stream().filter(dict -> dict.getValue().equals(usertype)).findFirst().orElse(null);
+            listData.add(sysDictDo == null ? "" : sysDictDo.getName());
+            listData.add(swUserManagementDo.getUsername());
+            listData.add(swUserManagementDo.getAddress());
+
+
             swBillManagementPaidDoList = managementPaidDos.stream()
                     .filter(info -> swBillingRecordDo.getId().equals(info.getPaymentrecordid()) &&
-                    swBillingRecordDo.getUsernumber().equals(info.getUsernumber()))
+                            swBillingRecordDo.getUsernumber().equals(info.getUsernumber()))
                     .sorted(Comparator.comparing(SwBillManagementPaidDo::getThismeterreadingdate))
                     .collect(Collectors.toList());
-            List<PrintReceiptVo.WaterUsageInfo> waterUsageInfoList = new ArrayList<>();
             for (SwBillManagementPaidDo swBillManagementPaidDo : swBillManagementPaidDoList) {
                 // 账单对应的用水信息
-                waterUsageInfo = new PrintReceiptVo.WaterUsageInfo();
-                waterUsageInfo.setMeterReadingDate(sdf.format(swBillManagementPaidDo.getThismeterreadingdate()));
-                waterUsageInfo.setPreviousReading(swBillManagementPaidDo.getLastmeterreading().stripTrailingZeros());
-                waterUsageInfo.setCurrentReading(swBillManagementPaidDo.getThismeterreading().stripTrailingZeros());
-                waterUsageInfo.setWaterUsage(swBillManagementPaidDo.getCurrentwateruse().stripTrailingZeros());
-                waterUsageInfo.setUnitPrice(swBillManagementPaidDo.getUnitprice().stripTrailingZeros());
-                waterUsageInfo.setTotalPrice(swBillManagementPaidDo.getOughttohavepaid().stripTrailingZeros());
-                waterUsageInfo.setReliefAmount(swBillManagementPaidDo.getFeewaiver().stripTrailingZeros());
-                waterUsageInfo.setPenalty(swBillManagementPaidDo.getLatefees().stripTrailingZeros());
-                waterUsageInfoList.add(waterUsageInfo);
+                listData.add(sdf.format(swBillManagementPaidDo.getThismeterreadingdate()));
+                listData.add(swBillManagementPaidDo.getLastmeterreading().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getThismeterreading().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getCurrentwateruse().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getUnitprice().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getOughttohavepaid().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getFeewaiver().stripTrailingZeros());
+                listData.add(swBillManagementPaidDo.getLatefees().stripTrailingZeros());
+            }
+            listData.add(NumberToChineseUppercaseUtils.convert(swBillingRecordDo.getPaidin()));
+            listData.add(swBillingRecordDo.getPaidin());
+            listData.add(currentUser.getCreateusername());
+            datas.add(listData);
+        }
+        /********数据组装结束************/
+        // 打印参数组装
+        String unit = "mm";
+        List<List<PrintReceiptVo>> returnData = new ArrayList<>();
+        PrintReceiptVo printReceiptVo;
+        // 获取配置信息
+        List<SwPrintRepairConfigDo> swPrintRepairConfigDos = swPrintRepairConfigDao.selectList(new LambdaQueryWrapper<SwPrintRepairConfigDo>()
+                .eq(SwPrintRepairConfigDo::getDeleted, "0")
+                .orderByAsc(SwPrintRepairConfigDo::getSerialnum));
+        for (List<Object> data : datas) {
+            List<PrintReceiptVo> receiptVoList= new ArrayList<>();
+            List<Object> basicData = data.subList(0, 7);
+            // 获取中间需要被巡航的数据
+            List<Object> loopData = data.subList(6, data.size() - 3);
+            // 获取最后3条记录
+            List<Object> footData = data.subList(data.size() - 3, data.size());
+            /*********用户基本信息打印参数组装*************/
+            for (int i = 0; i < basicData.size(); i++) {
+                printReceiptVo = new PrintReceiptVo();
+                if (i == 0) {
+                    printReceiptVo.setFp("1");//纵向打印
+                    printReceiptVo.setSp(swPrintRepairConfigDos.get(i).getTopspace().toString());
+                    printReceiptVo.setTp(swPrintRepairConfigDos.get(i).getLeftspace().toString());
+                    printReceiptVo.setFop(swPrintRepairConfigDos.get(i).getContent());
+                } else {
+                    printReceiptVo.setFp(swPrintRepairConfigDos.get(i).getTopspace() + unit);
+                    printReceiptVo.setSp(swPrintRepairConfigDos.get(i).getLeftspace() + unit);
+                    printReceiptVo.setTp(swPrintRepairConfigDos.get(i).getWidthspace() + unit);
+                    printReceiptVo.setFop(swPrintRepairConfigDos.get(i).getHeightspace() + unit);
+                    printReceiptVo.setFip(swPrintRepairConfigDos.get(i).getContent() + basicData.get(i-1));
+                }
+                receiptVoList.add(printReceiptVo);
             }
-            printReceiptVo.setWaterUsageInfos(waterUsageInfoList);
-            receiptVoList.add(printReceiptVo);
+            /*******************循环部分数据组装 ************************/
+            int initialTop = 0;
+            List<SwPrintRepairConfigDo> headConfig = swPrintRepairConfigDos.subList(7, 15);
+            // 表头
+            for (SwPrintRepairConfigDo swPrintRepairConfigDo : headConfig) {
+                printReceiptVo = new PrintReceiptVo();
+                printReceiptVo.setFp(swPrintRepairConfigDo.getTopspace() + unit);
+                printReceiptVo.setSp(swPrintRepairConfigDo.getLeftspace() + unit);
+                printReceiptVo.setTp(swPrintRepairConfigDo.getWidthspace() + unit);
+                printReceiptVo.setFop(swPrintRepairConfigDo.getHeightspace() + unit);
+                printReceiptVo.setFip(swPrintRepairConfigDo.getContent());
+                initialTop = swPrintRepairConfigDo.getTopspace();
+                receiptVoList.add(printReceiptVo);
+            }
+            // 内容
+            List<List<Object>> partition = Lists.partition(loopData, 8);
+            for (int i = 0; i < partition.size(); i++) {
+                initialTop = initialTop + 5 ;
+                List<Object> dataList = partition.get(i);
+                for (int j = 0; j < dataList.size(); j++) {
+                    printReceiptVo = new PrintReceiptVo();
+                    printReceiptVo.setFp(initialTop + unit);
+                    printReceiptVo.setSp(headConfig.get(j).getLeftspace() + unit);
+                    printReceiptVo.setTp(headConfig.get(j).getWidthspace() + unit);
+                    printReceiptVo.setFop(headConfig.get(j).getHeightspace() + unit);
+                    printReceiptVo.setFip(dataList.get(j).toString());
+                    receiptVoList.add(printReceiptVo);
+                }
+            }
+
+            /*****************金额等信息组装********************/
+            for (int i = 0; i < footData.size(); i++) {
+                printReceiptVo = new PrintReceiptVo();
+                printReceiptVo.setFp(swPrintRepairConfigDos.get(15 + i).getTopspace() + unit);
+                printReceiptVo.setSp(swPrintRepairConfigDos.get(15 + i).getLeftspace() + unit);
+                printReceiptVo.setTp(swPrintRepairConfigDos.get(15 + i).getWidthspace() + unit);
+                printReceiptVo.setFop(swPrintRepairConfigDos.get(15 + i).getHeightspace() + unit);
+                printReceiptVo.setFip(swPrintRepairConfigDos.get(15 + i).getContent() + footData.get(i));
+                receiptVoList.add(printReceiptVo);
+            }
+            returnData.add(receiptVoList);
         }
-        return R.ok(receiptVoList);
+        return R.ok(returnData);
     }
+
 }

+ 2 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwBillManagementUnpaidServiceImpl.java

@@ -78,11 +78,12 @@ public class SwBillManagementUnpaidServiceImpl extends ServiceImpl<SwBillManagem
 
         BigDecimal oldreading = swWaterUsageEntryDo.getThisreading();
         SwWaterUsageEntryDo waterUsageUpdateDo= new SwWaterUsageEntryDo();
+        waterUsageUpdateDo.setId(swWaterUsageEntryDo.getId());
         waterUsageUpdateDo.setThisreading(thisMeterReading);
         waterUsageUpdateDo.setModifyuserid(currentUser.getId());
         waterUsageUpdateDo.setModifyusername(currentUser.getName());
         waterUsageUpdateDo.setModifydate(new Date());
-        swWaterUsageEntryService.updateById(swWaterUsageEntryDo);
+        swWaterUsageEntryService.updateById(waterUsageUpdateDo);
 
         //2. 根据抄表户号查询用户修改最近读表数
         SwUserManagementDo swUserManagement = swUserManagementService.getBaseMapper()

+ 216 - 111
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwBillingRecordServiceImpl.java

@@ -2,10 +2,7 @@ package com.rongwei.zhsw.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.rongwe.zhsw.system.domain.SwBillManagementPaidDo;
-import com.rongwe.zhsw.system.domain.SwBillManagementUnpaidDo;
-import com.rongwe.zhsw.system.domain.SwBillingRecordDo;
-import com.rongwe.zhsw.system.domain.SwUserManagementDo;
+import com.rongwe.zhsw.system.domain.*;
 import com.rongwe.zhsw.system.dto.PaymentRequestDTO;
 import com.rongwei.rwadmincommon.system.vo.SysUserVo;
 import com.rongwei.rwcommon.base.R;
@@ -17,12 +14,16 @@ import com.rongwei.zhsw.system.service.SwBillManagementUnpaidService;
 import com.rongwei.zhsw.system.service.SwBillingRecordService;
 import com.rongwei.zhsw.system.service.SwUserManagementService;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
 import java.math.BigDecimal;
+import java.security.SecureRandom;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -56,6 +57,9 @@ public class SwBillingRecordServiceImpl extends ServiceImpl<SwBillingRecordDao,
     @Autowired
     private SwUserManagementService swUserManagementService;
 
+    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
+
+
 
     /**
      * 缴费记录生成
@@ -66,161 +70,262 @@ public class SwBillingRecordServiceImpl extends ServiceImpl<SwBillingRecordDao,
     @Override
     @Transactional(rollbackFor = Exception.class)
     public R windowPayment(PaymentRequestDTO paymentRequestDTO) throws Exception {
-        List<String> ids = paymentRequestDTO.getIds();
-        BigDecimal paidIn = paymentRequestDTO.getPaidin();
-        String datasource = paymentRequestDTO.getDatasource();
-        //1. 根据户号查询 待缴费 状态 无缴费记录的 的待缴费账单
-        LambdaQueryWrapper<SwBillManagementUnpaidDo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-        lambdaQueryWrapper.in(SwBillManagementUnpaidDo::getId, ids)
-                .eq(SwBillManagementUnpaidDo::getStatus,PENDINGSTATUS)
-                .eq(SwBillManagementUnpaidDo::getDeleted,"0");
 
-        List<SwBillManagementUnpaidDo> list = swBillManagementUnpaidService.list(lambdaQueryWrapper);
+        try {
 
-        //2.校验账单数据
-        checkBillingData(list,ids);
+            log.info("窗口缴费开始");
 
-        //生成缴费记录
-         addNewBillRecord(paidIn,datasource,list);
+            if (paymentRequestDTO.getIds()==null){
 
-        //5.删除 待收账单数据
-        swBillManagementUnpaidDao.deleteByIds(ids);
+                log.info("无账单缴费");
+                windowPaymentNoBill(paymentRequestDTO);
+            }else {
+
+                log.info("有账单缴费");
+                windowPaymentHasBill(paymentRequestDTO);
+            }
+
+            log.info("窗口缴费结束");
+
+        }catch (Exception e ){
+            log.error("缴费失败 {}",e.getMessage());
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            return R.error(e.getMessage());
+        }
 
         return R.ok();
     }
 
+    /**
+     * 有账单生成 缴费记录
+     *
+     * @param paymentRequestDTO
+     */
+    private void windowPaymentHasBill(PaymentRequestDTO paymentRequestDTO) {
+
+        List<String> ids = paymentRequestDTO.getIds();
+        // 查询待缴费账单
+        List<SwBillManagementUnpaidDo> unpaidBills = queryUnpaidBills(paymentRequestDTO.getIds());
+
+        //生成缴费记录
+        addNewBillRecord(paymentRequestDTO,unpaidBills);
 
+        //删除 待收账单数据
+        deleteUnpaidBills(ids);
+    }
 
     /**
-     * 生成新的缴费账单
-     *
-     * @param paidin
-     * @param datasource
-     * @param list
+     * 无账单生成缴费记录
+
      */
-    private void addNewBillRecord(BigDecimal paidin, String datasource, List<SwBillManagementUnpaidDo> list) {
-        SwBillingRecordDo add = new SwBillingRecordDo();
+    private void windowPaymentNoBill(PaymentRequestDTO paymentRequestDTO) {
+
+
+        //生成缴费记录
+        addNewBillRecord(paymentRequestDTO,null);
+
+    }
 
-        add.setId(SecurityUtil.getUUID())
+    /**
+     * 删除 待收账单数据
+     * @param ids
+     */
+    private void deleteUnpaidBills(List<String> ids) {
+        swBillManagementUnpaidDao.deleteByIds(ids);
+    }
+
+
+    /**
+     *  根据户号查询 待缴费 状态 无缴费记录的 的待缴费账单
+     * @param ids
+     * @return
+     */
+    private List<SwBillManagementUnpaidDo> queryUnpaidBills(List<String> ids) {
+        return swBillManagementUnpaidService.list(
+                new LambdaQueryWrapper<SwBillManagementUnpaidDo>()
+                        .in(SwBillManagementUnpaidDo::getId, ids)
+                        .eq(SwBillManagementUnpaidDo::getStatus, PENDINGSTATUS)
+                        .eq(SwBillManagementUnpaidDo::getDeleted, "0")
+        );
+    }
+
+    // 提取公共字段设置
+    private SwBillingRecordDo buildBaseBillingRecord( PaymentRequestDTO paymentRequestDTO, SysUserVo currentUser, SwUserManagementDo user) {
+        SwBillingRecordDo record = new SwBillingRecordDo();
+
+
+        return record.setId(SecurityUtil.getUUID())
                 .setChargedate(new Date())
                 .setPayfeesstatus(PAIDSTATUS)
                 .setYear(Calendar.getInstance().get(Calendar.YEAR))
-                .setUsername(list.get(0).getUsername())
-                .setUsernumber(list.get(0).getUsernumber())
-                .setUsertype(list.get(0).getUsertype())
-                .setWatertype(list.get(0).getWatertype())
-                .setAddress(list.get(0).getAddress());
-
-        //生成缴费编号 年月日 + 3位数 随机数
-        CreateBillingNumber(add);
-
-        //当前用户
-        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
-        add.setTollcollectorid(currentUser.getId());
-        add.setTollcollectorname(currentUser.getName());
-        add.setTenantid(currentUser.getTenantid())
+                .setUsername(user.getUsername())
+                .setUsernumber(user.getUsernumber())
+                .setUsertype(user.getUsertype())
+                .setWatertype(user.getWatertype())
+                .setAddress(user.getAddress())
+                .setTollcollectorid(currentUser.getId())
+                .setTollcollectorname(currentUser.getName())
+                .setTenantid(currentUser.getTenantid())
                 .setCreateuserid(currentUser.getId())
                 .setCreateusername(currentUser.getName())
                 .setCreatedate(new Date())
                 .setModifydate(new Date())
                 .setModifyuserid(currentUser.getId())
+                .setTenantid(currentUser.getTenantid())
+                .setDatasource(paymentRequestDTO.getDatasource())
+                 .setPaidin(paymentRequestDTO.getPaidin())
                 .setModifyusername(currentUser.getName());
+    }
+
+
+    /**
+     * 生成新的缴费账单
+     *
+     * @param paidin
+     * @param datasource
+     * @param paymentRequestDTO
+     * @param unpaidBills
+     */
+    private void addNewBillRecord(PaymentRequestDTO paymentRequestDTO, List<SwBillManagementUnpaidDo> list) {
+
+        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
+
+        //根据户号获取 用户记录
+        SwUserManagementDo user = swUserManagementService.getBaseMapper().
+                selectOne(new LambdaQueryWrapper<SwUserManagementDo>().eq(SwUserManagementDo::getUsernumber, paymentRequestDTO.getUsernumber()));
+
+
+        SwBillingRecordDo add = buildBaseBillingRecord(paymentRequestDTO,currentUser,user);
+
+
+        // 生成缴费编号
+        generateBillingNumber(add);
+
+        // 计算费用
+        calculateFees(list, add,user);
+
+
+        if(list!=null){
+            //生成已缴费账单
+            createBills(list,add,currentUser);
+        }
 
-        // list 汇总计算
-        BigDecimal allfeewaiver =new BigDecimal(0);
-        BigDecimal oughttohavepaid =new BigDecimal("0");
-        BigDecimal latefees =new BigDecimal(0);
-        List<SwBillManagementPaidDo> paidDos =new ArrayList<>();
-        for (SwBillManagementUnpaidDo unpaidDo : list) {
-            allfeewaiver = allfeewaiver.add(unpaidDo.getFeewaiver()==null?BigDecimal.ZERO:unpaidDo.getFeewaiver());
-            oughttohavepaid =oughttohavepaid.add(unpaidDo.getOughttohavepaid()==null?BigDecimal.ZERO:unpaidDo.getOughttohavepaid());
-            latefees = latefees.add(unpaidDo.getLatefees()==null?BigDecimal.ZERO:unpaidDo.getLatefees());
-
-            SwBillManagementPaidDo paidDo = new SwBillManagementPaidDo();
-            BeanUtils.copyProperties(unpaidDo,paidDo);
-            // 新生成的 已缴费账单
-            paidDo.setStatus(PAIDINSTATUS);
-            //缴费记录ID
-            paidDo.setPaymentrecordid(add.getId());
 
-            paidDo.setCreateuserid(currentUser.getId())
+
+        //更新用户余额
+        updateUserBalance(add,user);
+
+
+    }
+
+    private void createBills(List<SwBillManagementUnpaidDo> list, SwBillingRecordDo add, SysUserVo currentUser) {
+        List<SwBillManagementPaidDo> paidList = new ArrayList<>();
+
+        for (SwBillManagementUnpaidDo unpaid : list) {
+
+
+            SwBillManagementPaidDo paid = new SwBillManagementPaidDo();
+            BeanUtils.copyProperties(unpaid, paid);
+            // 新生成的 已缴费账单
+            paid.setStatus(PAIDINSTATUS)
+                    //缴费记录ID
+                    .setPaymentrecordid(add.getId())
+                    .setCreateuserid(currentUser.getId())
                     .setCreateusername(currentUser.getName())
                     .setCreatedate(new Date())
                     .setModifydate(new Date())
                     .setModifyuserid(currentUser.getId())
                     .setModifyusername(currentUser.getName());
-            paidDos.add(paidDo);
+            paidList.add(paid);
 
         }
-        //生成已经缴费账单
-        swBillManagementPaidService.saveBatch(paidDos);
+        // 保存已缴费账单
+        swBillManagementPaidService.saveBatch(paidList);
+    }
+
+    /**
+     * 更新用户余额
+     *
+     * @param add
+     * @param user
+     */
+    private void updateUserBalance(SwBillingRecordDo add, SwUserManagementDo user) {
+        BigDecimal balanceChange = add.getAfterpaymentbalance().subtract(user.getAccountbalance());
+        swUserManagementService.balanceAdd(user.getId(), balanceChange);
+    }
+
+
+
+    private void calculateFees(List<SwBillManagementUnpaidDo> list, SwBillingRecordDo add, SwUserManagementDo user) {
+
+
+        // 用户 账户余额
+        BigDecimal accountbalance = user.getAccountbalance()==null?BigDecimal.ZERO:user.getAccountbalance();
+        BigDecimal totalWaivers =BigDecimal.ZERO;
+        BigDecimal totalOught =BigDecimal.ZERO;
+        BigDecimal totalLateFees =BigDecimal.ZERO;
+
+
+        if (list!=null){
+            // 使用Stream API进行汇总计算
+             totalWaivers = list.stream()
+                    .map(SwBillManagementUnpaidDo::getFeewaiver)
+                    .filter(Objects::nonNull)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+             totalOught = list.stream()
+                    .map(SwBillManagementUnpaidDo::getOughttohavepaid)
+                    .filter(Objects::nonNull)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+             totalLateFees = list.stream()
+                    .map(SwBillManagementUnpaidDo::getLatefees)
+                    .filter(Objects::nonNull)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+        }
+
+
         //总减免
-        add.setAllfeewaiver(allfeewaiver);
+        add.setAllfeewaiver(totalWaivers);
         //原应缴
-        add.setOughttohavepaid(oughttohavepaid);
+        add.setOughttohavepaid(totalOught);
         //滞纳金
-        add.setLatefees(latefees);
-        //根据户号获取 用户记录
-        SwUserManagementDo swUserManagement = swUserManagementService.getBaseMapper().
-                selectOne(new LambdaQueryWrapper<SwUserManagementDo>().eq(SwUserManagementDo::getUsernumber, add.getUsernumber()));
-
-        // 用户 账户余额
-        BigDecimal accountbalance = swUserManagement.getAccountbalance()==null?BigDecimal.ZERO:swUserManagement.getAccountbalance();
+        add.setLatefees(totalLateFees);
         // 账户余额
         add.setAccountbalance(accountbalance);
         //原余额(元)   = 用户表 用户余额
         add.setOriginalbalance(accountbalance);
-        //实缴
-        add.setPaidin(paidin);
-        //1、当 【余额】 >=【原应缴(元)】-【总减免(元)】 -【滞纳金(元)】  时,【余额抵扣】字段=【原应缴(元)】-【总减免(元)】 -【滞纳金(元)】
-        //2、当 【余额】 <【原应缴(元)】-【总减免(元)】 -【滞纳金(元)】  时,【余额抵扣】字段=【账户余额(元)】
-        if(oughttohavepaid.subtract(allfeewaiver).subtract(latefees).compareTo(accountbalance)<0){
-            add.setBalancededuction(oughttohavepaid.subtract(allfeewaiver).subtract(latefees));
+        //1、当 【余额】 >=【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】  时,【余额抵扣】字段=【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】
+        //2、当 【余额】 <【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】  时,【余额抵扣】字段=【账户余额(元)】
+        if(totalOught.subtract(totalWaivers).add(totalLateFees).compareTo(accountbalance)<0){
+            add.setBalancededuction(totalOught.add(totalWaivers).subtract(totalLateFees));
         }else {
             add.setBalancededuction(accountbalance);
         }
-        // 【实际应缴(元)】=【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】-【余额抵扣(元)】
-        add.setActualdue(oughttohavepaid.subtract(allfeewaiver).add(latefees).subtract(add.getBalancededuction()));
+        // 【实际应缴(元)】  【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】 >0 = 【原应缴(元)】-【总减免(元)】 +【滞纳金(元)】 else  0
+        BigDecimal actualdue =BigDecimal.ZERO;
+        if (totalOught.subtract(totalWaivers).add(totalLateFees).compareTo(BigDecimal.ZERO)>-1){
+            actualdue=totalOught.subtract(totalWaivers).add(totalLateFees);
+        }
+        add.setActualdue(actualdue);
+
         //【实缴后余额(元)】=【账户余额】+【本次实缴(元-整)】- 原应缴 + 总减免 - 滞纳金
-        add.setAfterpaymentbalance(paidin.add(accountbalance).subtract(oughttohavepaid).add(allfeewaiver).subtract(latefees));
-        //数据来源
-        add.setDatasource(datasource);
-        //更新用户表 余额字段
-        swUserManagementService.balanceAdd(swUserManagement.getId(), add.getAfterpaymentbalance().subtract(accountbalance));
+        add.setAfterpaymentbalance(add.getPaidin().add(accountbalance).subtract(totalOught).add(totalWaivers).subtract(totalLateFees));
+
         swBillingRecordService.save(add);
     }
 
     /**
-     * 生成缴费编号  年月日 + 3位数 随机数
-     * @return
+     * 年月日 +
+     * @param add 3位数 随机数
      */
-    private void CreateBillingNumber(SwBillingRecordDo add) {
-        // 获取当前时间并格式化为 "yyyyMMddHHmmss"
+    private void generateBillingNumber(SwBillingRecordDo add) {
+        SecureRandom random = new SecureRandom();
+        int randomNumber = random.nextInt(1000);
+        String randomStr = String.format("%03d", randomNumber);
         LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
-        String formattedDateTime = now.format(formatter);
-
-        // 生成一个三位数的随机数
-        Random random = new Random();
-        int randomNumber = random.nextInt(1000); // 生成0到999之间的随机数
-        String randomStr = String.format("%03d", randomNumber); // 格式化为三位数,不足三位补零
-        add.setBillingnumber(formattedDateTime + randomStr);
-
-
+        add.setBillingnumber(now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + randomStr);
     }
 
-    /**
-     * 校验账单数据
-     *
-     * @param list
-     * @param ids
-     */
-    private void checkBillingData(List<SwBillManagementUnpaidDo> list,  List<String> ids) throws Exception {
-        //判空
-        if (list.isEmpty()) throw new Exception("该户号下待缴账单已全部缴费,请重新选择户号!");
-        //个别 被缴费
-        if (list.size() < ids.size()) {
-            throw new Exception("当前账单中存在已缴费的,请重新查询用户最新账单在确认缴费");
-        }
-    }
+
 }

+ 103 - 50
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/SwRefundRequestRecordServiceImpl.java

@@ -1,5 +1,5 @@
 package com.rongwei.zhsw.system.service.impl;
- 
+
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -9,6 +9,8 @@ import com.rongwei.rwcommon.base.R;
 import com.rongwei.rwcommon.utils.SecurityUtil;
 import com.rongwei.zhsw.system.dao.SwRefundRequestRecordDao;
 import com.rongwei.zhsw.system.service.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -18,6 +20,8 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
 import static com.rongwei.zhsw.system.utils.SaveConstans.billInfo.PENDINGSTATUS;
 import static com.rongwei.zhsw.system.utils.SaveConstans.billReccord.FULLREFUNDSTATUS;
 import static com.rongwei.zhsw.system.utils.SaveConstans.billReccord.PARTIALREFUNDSTATUS;
@@ -47,23 +51,51 @@ public class SwRefundRequestRecordServiceImpl extends ServiceImpl<SwRefundReques
     @Autowired
     private SwBillManagementUnpaidService swBillManagementUnpaidService;
 
+    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
+
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public R refundApplication(String id) {
+    public R refundApplication(String id) throws Exception {
 
-        //当前用户
-        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
+        try {
+            //当前用户
+            SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
 
-        //1.获取退款记录
-        SwRefundRequestRecordDO refundRequestRecordDO = swRefundRequestRecordService.getById(id);
+            //获取退款记录
+            SwRefundRequestRecordDO refundRequestRecordDO = swRefundRequestRecordService.getById(id);
 
-        // 缴费记录表更新:
-        updateBillRecord(refundRequestRecordDO,currentUser);
+            //用户表获取
+            SwUserManagementDo user = swUserManagementService.getBaseMapper().
+                    selectOne(new LambdaQueryWrapper<SwUserManagementDo>().eq(SwUserManagementDo::getUsernumber, refundRequestRecordDO.getUsernumber()));
 
-        BigDecimal balanceAdd =BigDecimal.ZERO;
+            //校验 退款金额
+            validateRefundAmount(refundRequestRecordDO,user);
 
-        //全额 退款
-        if (refundRequestRecordDO.getRefundmethod().equals(REFUNDMETHODALL)){
+            // 1.缴费记录表更新:
+            updateBillRecord(refundRequestRecordDO,currentUser);
+
+            //2. 更新退款记录
+            processRefund(refundRequestRecordDO, currentUser);
+
+            // 已缴账单记录表更新
+            migratePaidBillsToUnpaid(refundRequestRecordDO);
+
+            // 更新用户余额
+            updateUserBalance(refundRequestRecordDO,user);
+
+        }catch (Exception e){
+
+            log.error("退款失败 {}",e.getMessage());
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            return R.error(e.getMessage());
+        }
+
+
+
+        return R.ok();
+    }
+
+    private void processRefund(SwRefundRequestRecordDO refundRequestRecordDO, SysUserVo currentUser) {
             // 退款记录表更新 实退金额 退款操作人,操作时间
             swRefundRequestRecordService.update(new LambdaUpdateWrapper<SwRefundRequestRecordDO>()
                     .eq(SwRefundRequestRecordDO::getId, refundRequestRecordDO.getId())
@@ -73,58 +105,79 @@ public class SwRefundRequestRecordServiceImpl extends ServiceImpl<SwRefundReques
                     .set(SwRefundRequestRecordDO::getRefundoperatorname, currentUser.getName())
                     .set(SwRefundRequestRecordDO::getRefundtime,new Date())
             );
+    }
 
-            //预收账单记录表更新: 已缴账单记录表更新
-            updateOrSaveBills(refundRequestRecordDO.getPaymentrecordid());
-
-            //用户表更新:系统需要 将 对应用户信息中的【余额】进行更新,余额 =  当前用户余额 + 【余额抵扣 balancededuction
-            balanceAdd = refundRequestRecordDO.getBalancededuction();
-
-
-        } else if (refundRequestRecordDO.getRefundmethod().equals(REFUNDMETHODBALANCE)) {
-             // 差额退款
+    /**
+     * 更新用户表月
+     * @param refundRequestRecordDO
+     * @param user
+     */
+    private void updateUserBalance(SwRefundRequestRecordDO refundRequestRecordDO, SwUserManagementDo user) {
+        BigDecimal balanceChange = calculateBalanceChange(refundRequestRecordDO);
+        swUserManagementService.balanceAdd(user.getId(), balanceChange);
+    }
 
-           // 用户表更新:系统需要 将 对应用户信息中的【余额】进行更新,余额 =  当前用户余额 - 【退款金额】
-            balanceAdd = BigDecimal.ZERO.subtract(refundRequestRecordDO.getRefundamount());
+    /**
+     *   全额 用户表更新:系统需要 将 对应用户信息中的【余额】进行更新,余额 =  当前用户余额 + 【余额抵扣 balancededuction
+     *   差额   系统需要 将 对应用户信息中的【余额】进行更新,余额 =  当前用户余额 - 【退款金额】
+     *   negate 数值取反
+     * @param refundRequest
+     * @return
+     */
+    private BigDecimal calculateBalanceChange(SwRefundRequestRecordDO refundRequest) {
+        if (REFUNDMETHODALL.equals(refundRequest.getRefundmethod())) {
+            return refundRequest.getBalancededuction();
         }
+        return refundRequest.getRefundamount().negate();
+    }
 
-        //用户表更新
-        SwUserManagementDo swUserManagement = swUserManagementService.getBaseMapper().
-                selectOne(new LambdaQueryWrapper<SwUserManagementDo>().eq(SwUserManagementDo::getUsernumber, refundRequestRecordDO.getUsernumber()));
-        swUserManagementService.balanceAdd(swUserManagement.getId(), balanceAdd);
-
-
-        return R.ok();
+    /**
+     * 校验 退款金额 差额退款时候 退款金额不能大于用户余额
+     * @param refundRequestRecordDO
+     * @param user
+     */
+    private void validateRefundAmount(SwRefundRequestRecordDO refundRequestRecordDO, SwUserManagementDo user) {
+        if (REFUNDMETHODBALANCE.equals(refundRequestRecordDO.getRefundmethod())) {
+            if (refundRequestRecordDO.getRefundamount().compareTo(user.getAccountbalance()) > 0) {
+                throw new IllegalArgumentException("本次退款月不足,无法退款");
+            }
+        }
     }
 
     /**
      * 预收账单记录表更新:系统需要 将 对应的 缴费记录对应账单 信息 复制一份到  预收账单记录表中,并且 缴费状态标记状态为“待缴费”
      * 已缴账单记录表更新:系统需要 将 对应的 缴费记录对应账单 标记为删除
-     * @param paymentrecordid
+     * @param
      */
-    private void updateOrSaveBills(String paymentrecordid) {
-        List<SwBillManagementUnpaidDo> unpaidDoList =new ArrayList<>();
-        List<String> paidIds =new ArrayList<>();
-        List<SwBillManagementPaidDo> list = swBillManagementPaidService.list(new LambdaQueryWrapper<SwBillManagementPaidDo>()
-                .eq(SwBillManagementPaidDo::getPaymentrecordid,paymentrecordid)
-                .eq(SwBillManagementPaidDo::getDeleted,"0")
-        );
-        if (!list.isEmpty()){
-            for (SwBillManagementPaidDo paidDo : list){
-                // 已缴账单记录
-                paidIds.add(paidDo.getId());
-                //预收账单记录
-                SwBillManagementUnpaidDo unpaidDo = new SwBillManagementUnpaidDo();
-                BeanUtils.copyProperties(paidDo,unpaidDo);
-                unpaidDo.setId(SecurityUtil.getUUID());
-                unpaidDo.setStatus(PENDINGSTATUS);
-                unpaidDoList.add(unpaidDo);
+    private void migratePaidBillsToUnpaid(SwRefundRequestRecordDO swRefundRequestRecordDO) {
+        if (swRefundRequestRecordDO.getRefundmethod().equals(REFUNDMETHODALL)){
+
+            List<SwBillManagementPaidDo> paidBills = swBillManagementPaidService.list(new LambdaQueryWrapper<SwBillManagementPaidDo>()
+                    .eq(SwBillManagementPaidDo::getPaymentrecordid,swRefundRequestRecordDO.getPaymentrecordid())
+                    .eq(SwBillManagementPaidDo::getDeleted,"0")
+            );
+            if (!paidBills.isEmpty()){
+                List<SwBillManagementUnpaidDo> unpaidDoList =new ArrayList<>();
+                List<String> paidIds =new ArrayList<>();
+                for (SwBillManagementPaidDo paidDo : paidBills){
+                    // 已缴账单记录
+                    paidIds.add(paidDo.getId());
+                    //预收账单记录
+                    SwBillManagementUnpaidDo unpaidBill = new SwBillManagementUnpaidDo();
+                    BeanUtils.copyProperties(paidDo,unpaidBill);
+                    unpaidBill.setId(SecurityUtil.getUUID());
+                    unpaidBill.setStatus(PENDINGSTATUS);
+                    unpaidDoList.add(unpaidBill);
+                }
+
+                swBillManagementUnpaidService.saveBatch(unpaidDoList,200);
+                swBillManagementPaidService.getBaseMapper().selectBatchIds(paidIds);
             }
 
-            swBillManagementUnpaidService.saveBatch(unpaidDoList,200);
-            swBillManagementPaidService.getBaseMapper().selectBatchIds(paidIds);
+
         }
 
+
     }
 
     /**
@@ -134,7 +187,7 @@ public class SwRefundRequestRecordServiceImpl extends ServiceImpl<SwRefundReques
      * @param currentUser
      */
     private void updateBillRecord(SwRefundRequestRecordDO refundRequestRecordDO, SysUserVo currentUser) {
-        // 将对应的 【退款金额】【退款人】【退款时间】记录到 缴费记录表中,
+        // 将对应的 【退款金额】【退款人】【退款时间】记录到 缴费记录表中, 当前用户
         SwBillingRecordDo swBillingRecordUpdateDo = new SwBillingRecordDo();
         swBillingRecordUpdateDo.setId(refundRequestRecordDO.getPaymentrecordid());
         swBillingRecordUpdateDo.setRefundtime(new Date());

+ 155 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/NumberToChineseUppercaseUtils.java

@@ -0,0 +1,155 @@
+package com.rongwei.zhsw.system.utils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * NumberToChineseUppercaseUtils class
+ *
+ * @author XH
+ * @date 2025/03/20
+ */
+public class NumberToChineseUppercaseUtils {
+    private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
+    private static final String[] BASE_UNITS = {"", "拾", "佰", "仟"};
+    private static final String[] SECTION_UNITS = {"", "万", "亿", "兆"};
+    private static final String[] DECIMAL_UNITS = {"角", "分"};
+    public static String convert(BigDecimal amount) {
+        // 参数校验
+        if (amount == null) {
+            throw new IllegalArgumentException("金额不能为null");
+        }
+        if (amount.compareTo(new BigDecimal("10000000000000000")) >= 0) {
+            throw new IllegalArgumentException("金额超出最大转换范围");
+        }
+        if(amount.compareTo(BigDecimal.ZERO) == 0){
+            return NUMBERS[0];
+        }
+        // 处理负值
+        boolean isNegative = amount.compareTo(BigDecimal.ZERO) < 0;
+        amount = amount.abs();
+
+        // 四舍五入到分位
+        amount = amount.setScale(2, RoundingMode.HALF_UP);
+
+        // 分割整数和小数部分
+        BigInteger integerPart = amount.toBigInteger();
+        int decimalPart = amount.remainder(BigDecimal.ONE)
+                .multiply(new BigDecimal(100))
+                .intValue();
+
+        // 转换各部分
+        String chineseInteger = convertIntegerPart(integerPart);
+        String chineseDecimal = convertDecimalPart(decimalPart);
+
+        // 组合结果
+        StringBuilder result = new StringBuilder();
+        if (isNegative) result.append("负");
+        result.append(chineseInteger);
+
+        if ("元".equals(chineseInteger)) { // 处理纯小数情况
+            result.insert(0, "零");
+        }
+
+        result.append(chineseDecimal);
+
+        // 清理冗余零
+        return optimizeResult(result.toString());
+    }
+
+    private static String convertIntegerPart(BigInteger integerPart) {
+        if (integerPart.equals(BigInteger.ZERO)) {
+            return "";
+        }
+
+        List<Integer> sections = new ArrayList<>();
+        BigInteger temp = integerPart;
+        while (temp.compareTo(BigInteger.ZERO) > 0) {
+            sections.add(temp.mod(BigInteger.valueOf(10000)).intValue());
+            temp = temp.divide(BigInteger.valueOf(10000));
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = sections.size() - 1; i >= 0; i--) {
+            String sectionStr = convertSection(sections.get(i));
+            if (!sectionStr.isEmpty()) {
+                sb.append(sectionStr).append(SECTION_UNITS[i]);
+            }
+        }
+
+        if (sb.length() == 0) {
+            return "零元";
+        }
+
+        return sb.append("元").toString();
+    }
+
+    private static String convertSection(int section) {
+        if (section == 0) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        boolean lastIsZero = true; // 标记上一位是否是零
+
+        for (int i = 0; i < 4; i++) {
+            int divisor = (int) Math.pow(10, 3 - i);
+            int digit = section / divisor;
+            section %= divisor;
+
+            if (digit != 0) {
+                if (lastIsZero && sb.length() > 0) {
+                    sb.append(NUMBERS[0]);
+                }
+                sb.append(NUMBERS[digit]);
+                if (i != 3) { // 个位不加单位
+                    sb.append(BASE_UNITS[3 - i]);
+                }
+                lastIsZero = false;
+            } else {
+                lastIsZero = true;
+            }
+        }
+
+        return sb.toString().replaceAll("零+$", "");
+    }
+
+    private static String convertDecimalPart(int decimalPart) {
+        if (decimalPart == 0) {
+            return "整";
+        }
+
+        int jiao = decimalPart / 10;
+        int fen = decimalPart % 10;
+
+        StringBuilder sb = new StringBuilder();
+        if (jiao > 0) {
+            sb.append(NUMBERS[jiao]).append(DECIMAL_UNITS[0]);
+        }
+        if (fen > 0) {
+            sb.append(NUMBERS[fen]).append(DECIMAL_UNITS[1]);
+        }
+
+        return sb.toString();
+    }
+
+    private static String optimizeResult(String result) {
+        String optimized = result
+                .replaceAll("零+", "零")
+                .replaceAll("零([万亿兆])", "$1")
+                .replaceAll("零元", "元")
+                .replaceAll("零角零分$", "整")
+                .replaceAll("元整$", "元整");
+
+        // 处理纯小数情况(如:0.12 → 零元壹角贰分)
+        if (optimized.startsWith("元")) {
+            optimized = "零" + optimized;
+        }
+
+        return optimized;
+    }
+
+}

+ 1 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/ZHSWCommonUtils.java

@@ -64,7 +64,7 @@ public class ZHSWCommonUtils {
                 }
             }
         }
-        return currUser;
+        return currUser==null?  new SysUserVo():currUser;
     }
 
     public static <T extends BaseDo> void initModelGeneralParameters(T t, SysUserDo userVo) {

+ 33 - 2
zhsw-common/src/main/java/com/rongwei/zhsw/system/wechat/impl/AccountServiceImpl.java

@@ -57,6 +57,7 @@ public class AccountServiceImpl implements AccountService {
     private SwNotificationAnnouncementDao swNotificationAnnouncementDao;
     @Autowired
     private CommonBusinessDao commonBusinessDao;
+
     @Override
     public R bind(AccountBindVo accountBindVo) {
         log.info("开始执行户号绑定:{}", accountBindVo);
@@ -82,7 +83,12 @@ public class AccountServiceImpl implements AccountService {
         SwUserWechatDo swUserWechat = new SwUserWechatDo();
         swUserWechat.setId(SecurityUtil.getUUID());
 
-        swUserWechat.setDefaultaccount(accountBindVo.getDefaultAccount());
+        // 根据 openId 查询是否存在绑定记录
+        boolean exists = swUserWechatService.count(new LambdaQueryWrapper<SwUserWechatDo>()
+                .eq(SwUserWechatDo::getWechatsign, openId)
+                .eq(SwUserWechatDo::getDeleted, 0)) > 0;
+        // 如果不存在数据设置为默认账户(0),存在数据设置为非默认账户(1)
+        swUserWechat.setDefaultaccount(exists);
         swUserWechat.setGroupname(accountBindVo.getGroupType());
         // swUserWechat.setPhone(accountBindVo.getPhone());
         swUserWechat.setUserno(swUserManagementVo.getUsernumber());
@@ -157,8 +163,33 @@ public class AccountServiceImpl implements AccountService {
             throw new CustomException("解绑的户号为空");
         }
         String currentWeChatOpenId = WeChatUtils.getCurrentWeChatOpenId();
+        // OpenId 下的所有绑定记录
+        List<SwUserWechatDo> bindRecords = swUserWechatService.list(new LambdaQueryWrapper<SwUserWechatDo>()
+                .eq(SwUserWechatDo::getWechatsign, currentWeChatOpenId));
+        // 判断是否需要更新默认账户
+        if (bindRecords.size() >= 2) {
+            // 查询当前解绑的账户是否是默认账户
+            SwUserWechatDo currentAccount = swUserWechatService.getOne(new LambdaQueryWrapper<SwUserWechatDo>()
+                    .eq(SwUserWechatDo::getWechatsign, currentWeChatOpenId)
+                    .eq(SwUserWechatDo::getUserno, account));
+            if (currentAccount != null && !currentAccount.getDefaultaccount()) {
+                // 当前解绑的是默认账户,需要将下一条数据设置为默认账户
+                SwUserWechatDo nextAccount = bindRecords.stream()
+                        .filter(record -> !record.getUserno().equals(account)) // 排除当前解绑的账户
+                        .findFirst()
+                        .orElse(null);
+
+                if (nextAccount != null) {
+                    // 更新下一条数据为默认账户
+                    nextAccount.setDefaultaccount(false); // 设置为默认账户
+                    swUserWechatService.updateById(nextAccount);
+                }
+            }
+
+        }
         // 删除绑定关系
         swUserManagementService.getBaseMapper().unbindAccount(dsKey, currentWeChatOpenId, account);
+
         // 默认不刷新直接返回
         if (!accountUnbindVo.getRefresh()) {
             return R.ok();
@@ -171,7 +202,7 @@ public class AccountServiceImpl implements AccountService {
         return R.ok(allOwnerByOpenId);
     }
 
-    public R setDefaultAccount(AccountUnbindVo accountUnbindVo){
+    public R setDefaultAccount(AccountUnbindVo accountUnbindVo) {
         String account = accountUnbindVo.getAccount();
         String dsKey = accountUnbindVo.getDeKey();
         if (StringUtils.isBlank(account)) {

+ 1 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/wechat/impl/RegistrationServiceImpl.java

@@ -128,7 +128,7 @@ public class RegistrationServiceImpl implements RegistrationService {
         String filePath="/upload_files/"+pathSuffix+"/";
         // 微信临时文件的目录
         String tempFilePath = weChatUploadVo.getTempFilePath();
-        String fileName = tempFilePath.substring(tempFilePath.lastIndexOf("tmp/") + 4);
+        String fileName = tempFilePath.substring(tempFilePath.lastIndexOf("/") + 4);
         ImageScaleDto scaleDto = ImageScaleDto.builder().scaleFlag(false).build();
         FileUtil.uploadFile(Base64.getDecoder().decode(base64),filePath , fileName, scaleDto);
 

+ 2 - 0
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwBillManagementPaidDo.java

@@ -184,5 +184,7 @@ public class SwBillManagementPaidDo implements Serializable {
      * 缴费日期
      */
     private Date paymentdate;
+
+
 }
 

+ 46 - 46
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwBillingRecordDo.java

@@ -22,169 +22,169 @@ import java.util.Date;
 @TableName("sw_billing_record")
 public class SwBillingRecordDo implements Serializable {
     private static final long serialVersionUID = -25780597568495659L;
-/**
+    /**
      * 主键
      */
     private String id;
-/**
+    /**
      * 租户ID
      */
     private String tenantid;
-/**
+    /**
      * 扩展json格式配置
      */
     private String roption;
-/**
+    /**
      * 是否删除Y/N
      */
     private String deleted;
-/**
+    /**
      * 备注
      */
     private String remark;
-/**
+    /**
      * 创建时间
      */
     private Date createdate;
-/**
+    /**
      * 创建用户ID
      */
     private String createuserid;
-/**
+    /**
      * 修改日期
      */
     private Date modifydate;
-/**
+    /**
      * 修改用户ID
      */
     private String modifyuserid;
-/**
+    /**
      * 创建人
      */
     private String createusername;
-/**
+    /**
      * 修改人
      */
     private String modifyusername;
-/**
+    /**
      * 缴费编号
      */
     private String billingnumber;
-/**
+    /**
      * 收费日期
      */
     private Date chargedate;
-/**
+    /**
      * 收费员ID
      */
     private String tollcollectorid;
-/**
+    /**
      * 收费员名称
      */
     private String tollcollectorname;
-/**
+    /**
      * 户号
      */
     private String usernumber;
-/**
+    /**
      * 户名
      */
     private String username;
-/**
+    /**
      * 用水类型
      */
     private String watertype;
-/**
+    /**
      * 用户类别
      */
     private String usertype;
-/**
+    /**
      * 详细地址
      */
     private String address;
-/**
+    /**
      * 缴费状态
      */
     private String payfeesstatus;
-/**
+    /**
      * 原余额(元)
      */
     private BigDecimal originalbalance;
-/**
+    /**
      * 总减免
-(元)
+     * (元)
      */
     private BigDecimal allfeewaiver;
-/**
+    /**
      * 原应缴
-(元)
+     * (元)
      */
     private BigDecimal oughttohavepaid;
-/**
+    /**
      * 实际应缴
-(元)
+     * (元)
      */
     private BigDecimal actualdue;
-/**
+    /**
      * 实缴
-(元)
+     * (元)
      */
     private BigDecimal paidin;
-/**
+    /**
      * 缴费后余额
-(元)
+     * (元)
      */
     private BigDecimal afterpaymentbalance;
-/**
+    /**
      * 数据来源(窗口缴费,微信缴费,自动缴费)
      */
     private String datasource;
-/**
+    /**
      * 商户支付编号
      */
     private String merchantpaymentnumber;
-/**
+    /**
      * 微信支付订单号
      */
     private String wechatpayordernumber;
-/**
+    /**
      * 商品描述
      */
     private String productdescription;
-/**
+    /**
      * 支付金额
-(元)
+     * (元)
      */
     private BigDecimal amountpaid;
-/**
+    /**
      * 支付完成时间
      */
     private Date paymentcompletiontime;
-/**
+    /**
      * 订单创建时间
      */
     private Date ordercreationtime;
-/**
+    /**
      * 支付状态
      */
     private String paymentstatus;
-/**
+    /**
      * 年份(可能跨年 2024,2025)
      */
     private Integer year;
-/**
+    /**
      * 滞纳金
      */
     private BigDecimal latefees;
-/**
+    /**
      * 余额抵扣
      */
     private BigDecimal balancededuction;
-/**
+    /**
      * 总已缴
      */
     private BigDecimal totalpaidin;
-/**
+    /**
      * 充值缴费金额
      */
     private String topuppaymentamount;

+ 77 - 0
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwPrintRepairConfigDo.java

@@ -0,0 +1,77 @@
+package com.rongwe.zhsw.system.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import com.rongwei.rwcommon.base.BaseDo;
+import lombok.Data;
+
+/**
+ * 票据打印配置信息
+ * @TableName sw_print_repair_config
+ */
+@TableName(value ="sw_print_repair_config")
+@Data
+public class SwPrintRepairConfigDo extends BaseDo {
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 租户ID
+     */
+    private String tenantid;
+
+    /**
+     * 扩展json格式配置
+     */
+    private String roption;
+
+    /**
+     * 类型(1.PRINT_PAGESIZE,2.PRINT_TEXT)
+     */
+    private Integer type;
+
+    /**
+     * 所增打印项在纸张内的上边距的(单位mm)
+     */
+    private Integer topspace;
+
+    /**
+     * 所增打印项在纸张内的左边距(单位mm)
+     */
+    private Integer leftspace;
+
+    /**
+     * 打印区域的宽度(单位mm)
+     */
+    private Integer widthspace;
+
+    /**
+     * 打印区域的高度(单位mm)
+     */
+    private Integer heightspace;
+
+    /**
+     * 序号
+     */
+    private Integer serialnum;
+
+    /**
+     * 内容
+     */
+    private String content;
+
+    /**
+     * 是否循环打印
+     */
+    private Integer cycleprint;
+
+    /**
+     * 描述用处
+     */
+    private String descstr;
+}

+ 3 - 1
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwUserManagementDo.java

@@ -1,5 +1,6 @@
 package com.rongwe.zhsw.system.domain;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.rongwei.rwcommon.base.BaseDo;
@@ -69,8 +70,9 @@ public class SwUserManagementDo extends BaseDo {
     /**
      * 册号
      */
-    private String volumeno;
 
+    @TableField("VOLUMENO")
+    private String volumeno;
     /**
      * 账户余额
      */

+ 1 - 1
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwUserWechatDo.java

@@ -62,4 +62,4 @@ public class SwUserWechatDo  extends BaseDo {
      * 当前户主所属的分组(,逗号分隔)
      */
     private String groupname;
-}
+}

+ 2 - 0
zhsw-entity/src/main/java/com/rongwe/zhsw/system/dto/PaymentRequestDTO.java

@@ -13,4 +13,6 @@ public class PaymentRequestDTO {
     private List<String> ids;
     //数据来源
     private String  datasource;
+    //户号
+    private String usernumber;
 }

+ 20 - 34
zhsw-entity/src/main/java/com/rongwe/zhsw/system/vo/PrintReceiptVo.java

@@ -13,39 +13,25 @@ import java.util.List;
  */
 @Data
 public class PrintReceiptVo {
-    // 开票日期
-    private String printDateStr;
-    // 户号
-    private String account;
-    // 户名
-    private String name;
-    // 用户类型
-    private String userType;
-    // 地址
-    private String address;
-    // BigDecimal
-    private BigDecimal balance;
-
-    private List<WaterUsageInfo> waterUsageInfos;
-
-    @Data
-    public  static class WaterUsageInfo{
-        // 抄表日期
-        private String meterReadingDate;
-        // 上次读数
-        private BigDecimal previousReading;
-        //本次读数
-        private BigDecimal currentReading;
-        // 用水量
-        private BigDecimal waterUsage;
-        // 单价
-        private BigDecimal unitPrice;
-        // 金额
-        private BigDecimal totalPrice;
-        // 减免金额
-        private BigDecimal reliefAmount;
-        // 违约金
-        private BigDecimal penalty;
-    }
+    /**
+     * 第一个参数
+     */
+    private String fp;
+    /**
+     *  第二个参数
+     */
+    private String sp;
+    /**
+     *  第三个参数
+     */
+    private String tp;
+    /**
+     *  第四个参数
+     */
+    private String fop;
+    /**
+     *  第五个参数
+     */
+    private String fip;
 
 }

+ 25 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/system/controller/SwRefundRequestRecordController.java

@@ -0,0 +1,25 @@
+package com.rongwei.zhsw.system.controller;
+
+
+import com.rongwei.rwcommon.base.R;
+import com.rongwei.zhsw.system.service.SwRefundRequestRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+@RestController
+@RequestMapping("/swRefundRequestRecord")
+public class SwRefundRequestRecordController {
+
+    @Autowired
+    SwRefundRequestRecordService swRefundRequestRecordService;
+
+
+    @PostMapping("/refundApplication")
+    @ResponseBody
+    public R refundApplication(@RequestBody Map<String, Object> map) throws Exception {
+        swRefundRequestRecordService.refundApplication(map.get("id").toString());
+        return R.ok();
+    }
+}

+ 1 - 0
zhsw-server/src/main/resources/bootstrap-dev.yml

@@ -10,3 +10,4 @@ spring:
       discovery:
         server-addr: 127.0.0.1:8848
         namespace: cd047569-9470-4dfb-8663-b113d01cd30f
+        #cd047569-9470-4dfb-8663-b113d01cd30f