Forráskód Böngészése

新增
1、新增变更能够将差额滞后至某月账单的功能

liangwenxuan 2 hete
szülő
commit
929dc32f4e

+ 2 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/BedChangeRecordCreateReqVO.java

@@ -121,5 +121,7 @@ public class BedChangeRecordCreateReqVO {
      * 原始金额
      */
     private BigDecimal originalAmount;
+    @Schema(description = "滞后至月份", example = "2026-01")
+    private String hysteresisMonth;
 
 }

+ 3 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/CateringChangeRecordCreateReqVO.java

@@ -111,4 +111,7 @@ public class CateringChangeRecordCreateReqVO {
      * 原始金额
      */
     private BigDecimal originalAmount;
+
+    @Schema(description = "滞后至月份", example = "2026-01")
+    private String hysteresisMonth;
 }

+ 2 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/NurseChangeRecordCreateReqVO.java

@@ -117,5 +117,7 @@ public class NurseChangeRecordCreateReqVO {
      * 原始金额
      */
     private BigDecimal originalAmount;
+    @Schema(description = "滞后至月份", example = "2026-01")
+    private String hysteresisMonth;
 
 }

+ 2 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/business/vo/PriceChangeRecordCreateReqVO.java

@@ -69,5 +69,7 @@ public class  PriceChangeRecordCreateReqVO {
      * 原始金额
      */
     private BigDecimal originalAmount;
+    @Schema(description = "滞后至月份", example = "2026-01")
+    private String hysteresisMonth;
 
 }

+ 1 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/bpm/vo/ElderlyChangeRecordReqVO.java

@@ -75,6 +75,7 @@ public class ElderlyChangeRecordReqVO {
      * 原始金额
      */
     private BigDecimal originalAmount;
+    private String hysteresisMonth;
 
 
 }

+ 95 - 23
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java

@@ -270,11 +270,12 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         // 增加原始金额的更新,因为原始金额是后续增加的字段,需要补充
         bedChangeRecordDO.setOriginalAmount(currentExpense);
         changeRecordMapper.updateById(bedChangeRecordDO);
+        // 滞后月
+        String hysteresisMonth = bedChangeRecordDO.getHysteresisMonth();
         // 2. 对比变更后的价格
         BigDecimal changeExpense = bedChangeRecordDO.getActualAmount();
 
-        // 3. 生成两条日常费用
-//        LocalDate now = LocalDate.now();
+        // 3. 生成日常费用
         BigDecimal daysInCurrentMonth = BigDecimal.valueOf(bedChangeRecordDO.getChangeDate().lengthOfMonth());
         LocalDate firstDayOfMonth = bedChangeRecordDO.getChangeDate().withDayOfMonth(1);
         // 原价格使用天数
@@ -282,14 +283,7 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         LocalDate endDay = bizUtil.getEndDateWithExpireDate(elderlyId,null,firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth()));
         // 新价格使用天数
         BigDecimal changeDays = new BigDecimal(Math.abs(ChronoUnit.DAYS.between(endDay,bedChangeRecordDO.getChangeDate()))+1);
-
-
-
-
-
-
 //        BED_CHANGE_DAILY_PAY_REMARK
-
 //        String currentRemark = String.format(BED_CHANGE_DAILY_REFUND_REMARK, bedChangeRecordDO.getChangeDate(),
 //                chargeCategory.getItemName(), currentExpense.setScale(2),
 //                bedChangeRecordDO.getExpectName(), changeExpense.setScale(2), firstDayOfMonth,
@@ -341,13 +335,44 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
             finalAmount = changeFinalAmount.subtract(currentFinalAmount);
         }
         if(finalAmount.compareTo(BigDecimal.ZERO) != 0){
+            DateTimeFormatter billingMonthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
+            String changeBillingMonth = bedChangeRecordDO.getChangeDate().format(billingMonthFormatter);
+            YearMonth changeYearMonth = YearMonth.parse(changeBillingMonth, billingMonthFormatter);
+            YearMonth hysteresisYearMonth = null;
+            if (StringUtils.isNotBlank(hysteresisMonth)) {
+                try {
+                    hysteresisYearMonth = YearMonth.parse(hysteresisMonth, billingMonthFormatter);
+                } catch (Exception ignored) {
+                    hysteresisYearMonth = null;
+                }
+            }
             Date currentDate = new Date();
             BigDecimal dailyExpensesDOAmount = finalAmount;
             // 查询已生成账单,对生效期内的已生成账单增加日常费用记录
             List<ExpenseOrderDO> generateExpenseOrder = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                     .eq(ExpenseOrderDO::getElderId, elderlyId)
-                    .ge(ExpenseOrderDO::getBillingMonth, bedChangeRecordDO.getChangeDate().format(DateTimeFormatter.ofPattern("yyyy-MM"))));
+                    .ge(ExpenseOrderDO::getBillingMonth, changeBillingMonth));
             if (generateExpenseOrder.size() > 0) {
+                List<String> targetBillingMonths = new ArrayList<>(generateExpenseOrder.size());
+                Set<String> targetBillingMonthSet = new HashSet<>(generateExpenseOrder.size());
+                for (ExpenseOrderDO e : generateExpenseOrder) {
+                    String targetBillingMonth = resolveAttributionBillMonth(e.getBillingMonth(), changeYearMonth, hysteresisYearMonth);
+                    targetBillingMonths.add(targetBillingMonth);
+                    targetBillingMonthSet.add(targetBillingMonth);
+                }
+
+                Map<String, ExpenseOrderDO> targetOrderMap = new HashMap<>();
+                if (CollectionUtil.isNotEmpty(targetBillingMonthSet)) {
+                    List<ExpenseOrderDO> targetOrders = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
+                            .eq(ExpenseOrderDO::getElderId, elderlyId)
+                            .in(ExpenseOrderDO::getBillingMonth, targetBillingMonthSet)
+                            .orderByDesc(ExpenseOrderDO::getCreatedTime));
+                    for (ExpenseOrderDO targetOrder : targetOrders) {
+                        targetOrderMap.putIfAbsent(targetOrder.getBillingMonth(), targetOrder);
+                    }
+                }
+
+                YearMonth finalHysteresisYearMonth = hysteresisYearMonth;
                 List<DailyExpensesDO> currentDailyExpensesDOList= generateExpenseOrder.stream().map((e) -> {
                     DailyExpensesDO currentDailyExpensesDO = new DailyExpensesDO();
                     currentDailyExpensesDO.setElderId(elderlyId);
@@ -356,7 +381,7 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
                     currentDailyExpensesDO.setItemName(chargeCategory.getItemName());
                     currentDailyExpensesDO.setType(2);
                     currentDailyExpensesDO.setPrice(changeExpense.setScale(2));
-                    if(bedChangeRecordDO.getChangeDate().format(DateTimeFormatter.ofPattern("yyyy-MM")).equals(e.getBillingMonth())){
+                    if(changeBillingMonth.equals(e.getBillingMonth())){
                         currentDailyExpensesDO.setAmount(dailyExpensesDOAmount);
                         currentDailyExpensesDO.setStartDate(bedChangeRecordDO.getChangeDate());
                         currentDailyExpensesDO.setEndDate(endDay);
@@ -373,10 +398,13 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
                     currentDailyExpensesDO.setCreatedTime(currentDate);
                     currentDailyExpensesDO.setAccountingTime(currentDate);
                     currentDailyExpensesDO.setCount(1);
-                    currentDailyExpensesDO.setAttributionBillTime(e.getBillingMonth());
-                    // 未缴费并且未锁定的账单
-                    if(!(e.getPayStatus().equals(BooleanEnum.TRUE.getValue())) && !e.getIsLock()){
+                    String targetBillingMonth = resolveAttributionBillMonth(e.getBillingMonth(), changeYearMonth, finalHysteresisYearMonth);
+                    currentDailyExpensesDO.setAttributionBillTime(targetBillingMonth);
+                    ExpenseOrderDO targetExpenseOrder = targetOrderMap.get(targetBillingMonth);
+                    if(targetExpenseOrder != null && !(targetExpenseOrder.getPayStatus().equals(BooleanEnum.TRUE.getValue())) && !targetExpenseOrder.getIsLock()){
                         currentDailyExpensesDO.setIsGenerateBill(BooleanEnum.TRUE.getValue());
+                    } else {
+                        currentDailyExpensesDO.setIsGenerateBill(BooleanEnum.FALSE.getValue());
                     }
                     return currentDailyExpensesDO;
                 }).collect(Collectors.toList());
@@ -385,12 +413,11 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
                 // 为未缴费的账单创建账单明细项并更新账单金额
                 // 不需要做日常费用isGenerateBill字段更新,因为上面插入时已经完成了,减少了数据库的操作
                 for (int i = 0; i < generateExpenseOrder.size(); i++) {
-                    ExpenseOrderDO e = generateExpenseOrder.get(i);
                     DailyExpensesDO currentDailyExpensesDO = currentDailyExpensesDOList.get(i);
-                    // 未缴费并且未锁定的账单
-                    if(!e.getPayStatus().equals(BooleanEnum.TRUE.getValue()) && !e.getIsLock()){
+                    ExpenseOrderDO targetExpenseOrder = targetOrderMap.get(targetBillingMonths.get(i));
+                    if(targetExpenseOrder != null && !targetExpenseOrder.getPayStatus().equals(BooleanEnum.TRUE.getValue()) && !targetExpenseOrder.getIsLock()){
                         ExpenseOrderItemDO expenseOrderItemDO = new ExpenseOrderItemDO();
-                        expenseOrderItemDO.setExpenseOrderId(e.getId());
+                        expenseOrderItemDO.setExpenseOrderId(targetExpenseOrder.getId());
                         expenseOrderItemDO.setSourceExpenseItemId(currentDailyExpensesDO.getId());
                         expenseOrderItemDO.setExpenseSource(BusinessConstants.DAILY_EXPENSES);
                         expenseOrderItemDO.setItemCategoryName(currentDailyExpensesDO.getItemCategory());
@@ -406,25 +433,30 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
                         expenseOrderItemDO.setEndDate(currentDailyExpensesDO.getEndDate());
                         expenseOrderItemDO.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
                         expenseOrderItemDO.setCreatedTime(currentDate);
-                        expenseOrderItemDO.setTenantId(e.getTenantId());
+                        expenseOrderItemDO.setTenantId(targetExpenseOrder.getTenantId());
                         expenseOrderItemDO.setPayStatus(0); // 未缴费状态
                         expenseOrderItemMapper.insert(expenseOrderItemDO);
                         
                         // 更新账单金额
-                        BigDecimal currentAmount = e.getActualAmount() != null ? e.getActualAmount() : BigDecimal.ZERO;
+                        BigDecimal currentAmount = targetExpenseOrder.getActualAmount() != null ? targetExpenseOrder.getActualAmount() : BigDecimal.ZERO;
                         BigDecimal newAmount = currentAmount.add(expenseOrderItemDO.getTotalAmount());
                         ExpenseOrderDO updateExpenseOrderDO = new ExpenseOrderDO();
-                        updateExpenseOrderDO.setId(e.getId());
+                        updateExpenseOrderDO.setId(targetExpenseOrder.getId());
                         updateExpenseOrderDO.setActualAmount(newAmount);
                         expenseOrderMapper.updateById(updateExpenseOrderDO);
+                        targetExpenseOrder.setActualAmount(newAmount);
                     }
                 }
             }
             // 生效的当月查询是否有账单,无账单则生成日常费用,有账单的情况上面已生成不用重复生成
             ExpenseOrderDO expenseOrder = expenseOrderMapper.selectOne(new LambdaQueryWrapperX<ExpenseOrderDO>()
                     .eq(ExpenseOrderDO::getElderId, elderlyId)
-                    .eq(ExpenseOrderDO::getBillingMonth, bedChangeRecordDO.getChangeDate().format(DateTimeFormatter.ofPattern("yyyy-MM"))));
+                    .eq(ExpenseOrderDO::getBillingMonth, changeBillingMonth));
             if(expenseOrder == null){
+                String targetBillingMonth = resolveAttributionBillMonth(changeBillingMonth, changeYearMonth, hysteresisYearMonth);
+                ExpenseOrderDO targetExpenseOrder = expenseOrderMapper.selectOne(new LambdaQueryWrapperX<ExpenseOrderDO>()
+                        .eq(ExpenseOrderDO::getElderId, elderlyId)
+                        .eq(ExpenseOrderDO::getBillingMonth, targetBillingMonth));
                 DailyExpensesDO currentDailyExpensesDO = new DailyExpensesDO();
                 currentDailyExpensesDO.setElderId(elderlyId);
                 currentDailyExpensesDO.setItemId(chargeCategory.getOverheadChargeId());
@@ -440,8 +472,39 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
                 currentDailyExpensesDO.setEndDate(endDay);
                 currentDailyExpensesDO.setAccountingTime(currentDate);
                 currentDailyExpensesDO.setCount(1);
-                currentDailyExpensesDO.setAttributionBillTime(bedChangeRecordDO.getChangeDate().format(DateTimeFormatter.ofPattern("yyyy-MM")));
+                currentDailyExpensesDO.setAttributionBillTime(targetBillingMonth);
+                if(targetExpenseOrder != null && !targetExpenseOrder.getPayStatus().equals(BooleanEnum.TRUE.getValue()) && !targetExpenseOrder.getIsLock()){
+                    currentDailyExpensesDO.setIsGenerateBill(BooleanEnum.TRUE.getValue());
+                } else {
+                    currentDailyExpensesDO.setIsGenerateBill(BooleanEnum.FALSE.getValue());
+                }
                 dailyExpensesMapper.insert(currentDailyExpensesDO);
+                if(currentDailyExpensesDO.getIsGenerateBill().equals(BooleanEnum.TRUE.getValue())){
+                    ExpenseOrderItemDO expenseOrderItemDO = new ExpenseOrderItemDO();
+                    expenseOrderItemDO.setExpenseOrderId(targetExpenseOrder.getId());
+                    expenseOrderItemDO.setSourceExpenseItemId(currentDailyExpensesDO.getId());
+                    expenseOrderItemDO.setExpenseSource(BusinessConstants.DAILY_EXPENSES);
+                    expenseOrderItemDO.setItemCategoryName(currentDailyExpensesDO.getItemCategory());
+                    expenseOrderItemDO.setItemName(currentDailyExpensesDO.getItemName());
+                    expenseOrderItemDO.setPrice(currentDailyExpensesDO.getPrice());
+                    expenseOrderItemDO.setActualPrice(currentDailyExpensesDO.getPrice());
+                    expenseOrderItemDO.setTotalAmount(currentDailyExpensesDO.getAmount());
+                    expenseOrderItemDO.setRoundAmount(currentDailyExpensesDO.getAmount().setScale(0, RoundingMode.HALF_UP));
+                    expenseOrderItemDO.setRoundTwoDecimalAmount(currentDailyExpensesDO.getAmount().setScale(2, RoundingMode.HALF_UP));
+                    expenseOrderItemDO.setCount(currentDailyExpensesDO.getCount());
+                    expenseOrderItemDO.setType(currentDailyExpensesDO.getType());
+                    expenseOrderItemDO.setStartDate(currentDailyExpensesDO.getStartDate());
+                    expenseOrderItemDO.setEndDate(currentDailyExpensesDO.getEndDate());
+                    expenseOrderItemDO.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
+                    expenseOrderItemDO.setCreatedTime(currentDate);
+                    expenseOrderItemDO.setTenantId(targetExpenseOrder.getTenantId());
+                    expenseOrderItemDO.setPayStatus(0);
+                    expenseOrderItemMapper.insert(expenseOrderItemDO);
+
+                    BigDecimal currentAmount = targetExpenseOrder.getActualAmount() != null ? targetExpenseOrder.getActualAmount() : BigDecimal.ZERO;
+                    BigDecimal newAmount = currentAmount.add(expenseOrderItemDO.getTotalAmount());
+                    expenseOrderMapper.updateById(new ExpenseOrderDO().setId(targetExpenseOrder.getId()).setActualAmount(newAmount));
+                }
             }
         }
 
@@ -1018,4 +1081,13 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
         }
         throw exception(ErrorCodeConstants.CHANGE_START_DATE_GREATER_EXPIRE_DATE);
     }
+
+    private String resolveAttributionBillMonth(String sourceBillingMonth, YearMonth changeYearMonth, YearMonth hysteresisYearMonth) {
+        if (hysteresisYearMonth == null || changeYearMonth == null || StringUtils.isBlank(sourceBillingMonth)) {
+            return sourceBillingMonth;
+        }
+        YearMonth sourceYearMonth = YearMonth.parse(sourceBillingMonth);
+        long monthOffset = ChronoUnit.MONTHS.between(changeYearMonth, sourceYearMonth);
+        return hysteresisYearMonth.plusMonths(monthOffset).toString();
+    }
 }

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/pay/WeChatPayController.java

@@ -87,6 +87,9 @@ public class WeChatPayController {
         WechatMiniPayRequestInfoDO wechatMiniPayRequestInfoDO = wechatMiniPayRequestInfoMapper.selectOne(new LambdaQueryWrapperX<WechatMiniPayRequestInfoDO>()
                 .eq(WechatMiniPayRequestInfoDO::getStatus, 1)
                 .eq(WechatMiniPayRequestInfoDO::getTenantId, req.getTenantId()));
+        if(wechatMiniPayRequestInfoDO == null){
+            return CommonResult.error(201,"该机构没有微信支付相关信息,请先开通微信支付");
+        }
         String merchantSerialNumber = CertUtils.getMerchantSerialNumberFromPem(wechatMiniPayRequestInfoDO.getCertPem());
         // 1. 构建配置类
         Config config =

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ElderlyChangeRecordDO.java

@@ -122,4 +122,9 @@ public class ElderlyChangeRecordDO extends BaseDO {
 
     private Long tenantId;
 
+    /**
+     * 滞后至月份
+     */
+    private String hysteresisMonth;
+
 }