Merge remote-tracking branch 'origin/master' into CLXCZC

# Conflicts:
#	v5/apps-customize/src/main/java/com/seeyon/apps/src_leasebill/controller/LeaseBillController.java
#	v5/apps-customize/src/main/java/com/seeyon/apps/src_leasebill/dao/impl/LeaseBillDaoImpl.java
#	v5/apps-customize/src/main/java/com/seeyon/apps/src_leasebill/util/LeaseBillUtil.java
This commit is contained in:
2026-06-05 18:01:56 +08:00
3 changed files with 75 additions and 27 deletions

View File

@@ -117,7 +117,6 @@ public class LeaseBillController extends BaseController {
} }
log.info("前端入参:{}", jsonObject.toString()); log.info("前端入参:{}", jsonObject.toString());
try { try {
// ===================== 2. 账单编号处理 ===================== // ===================== 2. 账单编号处理 =====================
String bdidValue = jsonObject.getString("bdid"); String bdidValue = jsonObject.getString("bdid");
@@ -235,11 +234,11 @@ public class LeaseBillController extends BaseController {
res.put("success", false); res.put("success", false);
res.put("s", "生成账单失败:" + e.getMessage()); res.put("s", "生成账单失败:" + e.getMessage());
} }
render(response, JSONUtil.toJSONString(res)); render(response, JSONUtil.toJSONString(res));
return null; return null;
} }
// ======================== 输出JSON ======================== // ======================== 输出JSON ========================
private void render(HttpServletResponse response, String text) { private void render(HttpServletResponse response, String text) {
response.setContentType("application/json;charset=UTF-8"); response.setContentType("application/json;charset=UTF-8");
@@ -251,6 +250,7 @@ public class LeaseBillController extends BaseController {
} }
// ======================== 配置 ======================== // ======================== 配置 ========================
public ConfigVo getYdctLeaseBillConfig() { public ConfigVo getYdctLeaseBillConfig() {
return cstConfigApi.getConfig(getPluginId()); return cstConfigApi.getConfig(getPluginId());
} }

View File

@@ -15,16 +15,30 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* 租金账单DAO实现类
* 功能:查询、删除账单主表和明细表数据
*/
public class LeaseBillDaoImpl implements ILeaseBillDao { public class LeaseBillDaoImpl implements ILeaseBillDao {
private LeaseBillConfigProvider configProvider = (LeaseBillConfigProvider) AppContext.getBean("leaseBillConfigProvider"); /** 配置提供者 */
private FieldDisplayNameQueryService fieldDisplayNameQueryService = (FieldDisplayNameQueryService) AppContext.getBean("fieldDisplayNameQueryService"); private final LeaseBillConfigProvider configProvider =
(LeaseBillConfigProvider) AppContext.getBean("leaseBillConfigProvider");
private String getFormNo(){ /** 字段名称查询服务 */
private final FieldDisplayNameQueryService fieldDisplayNameQueryService =
(FieldDisplayNameQueryService) AppContext.getBean("fieldDisplayNameQueryService");
/**
* 获取表单编号
*/
private String getFormNo() {
return configProvider.getBizConfigByKey(LeaseBillConstant.assistiveFormNo); return configProvider.getBizConfigByKey(LeaseBillConstant.assistiveFormNo);
} }
/**
* 根据账单编号查询账单ID列表
*/
@Override @Override
public List<String> leaseBillByCode(String code) throws BusinessException, SQLException { public List<String> leaseBillByCode(String code) throws BusinessException, SQLException {
List<String> lists = new ArrayList<String>(); List<String> lists = new ArrayList<String>();
@@ -40,6 +54,9 @@ public class LeaseBillDaoImpl implements ILeaseBillDao {
return lists; return lists;
} }
/**
* 根据ID删除账单主表数据
*/
@Override @Override
public int deleteBillById(String id) throws BusinessException, SQLException { public int deleteBillById(String id) throws BusinessException, SQLException {
TableContext tableContext = FormTableExecutor.master(getFormNo()); TableContext tableContext = FormTableExecutor.master(getFormNo());
@@ -48,12 +65,15 @@ public class LeaseBillDaoImpl implements ILeaseBillDao {
return FormTableExecutor.delete(tableContext, conditions); return FormTableExecutor.delete(tableContext, conditions);
} }
/**
* 根据主表ID删除账单明细表数据
*/
@Override @Override
public int deleteBillsByBillId(String formmainId) throws BusinessException, SQLException { public int deleteBillsByBillId(String formmainId) throws BusinessException, SQLException {
String tableName = configProvider.getBizConfigByKey(LeaseBillConstant.billAssistiveTableName); String tableName = configProvider.getBizConfigByKey(LeaseBillConstant.billAssistiveTableName);
TableContext sub = FormTableExecutor.sub(getFormNo(), tableName); TableContext sub = FormTableExecutor.sub(getFormNo(), tableName);
List<FormWhereCondition> conditions = new ArrayList<>(); List<FormWhereCondition> conditions = new ArrayList<>();
conditions.add(FormWhereCondition.build().display("formmain_id").value(formmainId)); conditions.add(FormWhereCondition.build().display("formmain_id").value(formmainId));
return FormTableExecutor.delete(sub,conditions); return FormTableExecutor.delete(sub, conditions);
} }
} }

View File

@@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.src_leasebill.config.FieldDisplayNameQueryService; import com.seeyon.apps.src_leasebill.config.FieldDisplayNameQueryService;
import com.seeyon.ctp.common.AppContext; import com.seeyon.ctp.common.AppContext;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
@@ -29,6 +31,11 @@ public class LeaseBillUtil {
*/ */
private final DateUtil dateUtil = new DateUtil(); private final DateUtil dateUtil = new DateUtil();
/**
* 金额精度保留2位小数
*/
private static final int MONEY_SCALE = 2;
// ======================== 【1】主方法生成租金账单支持一次性/周期) ======================== // ======================== 【1】主方法生成租金账单支持一次性/周期) ========================
/** /**
@@ -70,6 +77,7 @@ public class LeaseBillUtil {
return createCycleBills(startTime, endTime, isMonthLastDay, payCycleMonths, params, chargeType); return createCycleBills(startTime, endTime, isMonthLastDay, payCycleMonths, params, chargeType);
} }
// ======================== 【2】按年周期账单版本1 ======================== // ======================== 【2】按年周期账单版本1 ========================
/** /**
@@ -92,6 +100,7 @@ public class LeaseBillUtil {
return createCycleBills(startTime, endTime, isMonthLastDay, payCycleMonths, params, chargeType); return createCycleBills(startTime, endTime, isMonthLastDay, payCycleMonths, params, chargeType);
} }
// ======================== 【3】按自然年切割账单版本2 ======================== // ======================== 【3】按自然年切割账单版本2 ========================
/** /**
@@ -135,27 +144,26 @@ public class LeaseBillUtil {
nextYearStart.add(Calendar.DATE, 1); nextYearStart.add(Calendar.DATE, 1);
int monthCount = dateUtil.betweenMonthByTwoCalendar(yearBaseCal, nextYearStart); int monthCount = dateUtil.betweenMonthByTwoCalendar(yearBaseCal, nextYearStart);
double rent = calculateRent(monthCount, params, chargeType); String rent = calculateRent(monthCount, params, chargeType);
bill.put(fieldDisplayNameService.getDisplayName("租费"), String.valueOf(rent)); bill.put(fieldDisplayNameService.getDisplayName("租费"), rent);
bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(tempStart.getTime())); bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(tempStart.getTime()));
yearBaseCal = (Calendar) tempStart.clone(); yearBaseCal = (Calendar) tempStart.clone();
} else { } else {
// 最后一个年度 → 不足一年 // 最后一个年度 → 不足一年
int monthCount = dateUtil.betweenMonthByTwoCalendar(yearBaseCal, endTime); int monthCount = dateUtil.betweenMonthByTwoCalendar(yearBaseCal, endTime);
double rent = calculateRent(monthCount, params, chargeType); String rent = calculateRent(monthCount, params, chargeType);
Calendar realEnd = (Calendar) endTime.clone(); Calendar realEnd = (Calendar) endTime.clone();
realEnd.add(Calendar.DATE, -1); realEnd.add(Calendar.DATE, -1);
bill.put(fieldDisplayNameService.getDisplayName("租费"), String.valueOf(rent)); bill.put(fieldDisplayNameService.getDisplayName("租费"), rent);
bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime())); bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime()));
} }
// 下一期开始时间 = 当前结束时间 + 1天 // 下一期开始时间 = 当前结束时间 + 1天
tempStart.add(Calendar.DATE, 1); tempStart.add(Calendar.DATE, 1);
// 👆 这里已经修复,删除了错误的 calendar.add(...)
// 如果是月末模式,设置为当月最后一天 // 如果是月末模式,设置为当月最后一天
if (isMonthLastDay) { if (isMonthLastDay) {
@@ -176,7 +184,7 @@ public class LeaseBillUtil {
private Map<String, String> createOneTimeBill(Calendar startTime, Calendar endTime, int totalMonths, private Map<String, String> createOneTimeBill(Calendar startTime, Calendar endTime, int totalMonths,
JSONObject params, String chargeType) { JSONObject params, String chargeType) {
Map<String, String> bill = new HashMap<>(); Map<String, String> bill = new HashMap<>();
double rent = calculateRent(totalMonths, params, chargeType); String rent = calculateRent(totalMonths, params, chargeType);
bill.put(fieldDisplayNameService.getDisplayName("开始日期"), sdf.format(startTime.getTime())); bill.put(fieldDisplayNameService.getDisplayName("开始日期"), sdf.format(startTime.getTime()));
@@ -185,7 +193,7 @@ public class LeaseBillUtil {
realEnd.add(Calendar.DATE, -1); realEnd.add(Calendar.DATE, -1);
bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime())); bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime()));
bill.put(fieldDisplayNameService.getDisplayName("租费"), String.valueOf(rent)); bill.put(fieldDisplayNameService.getDisplayName("租费"), rent);
return bill; return bill;
} }
@@ -219,18 +227,18 @@ public class LeaseBillUtil {
if (periodEnd.before(endTime)) { if (periodEnd.before(endTime)) {
// 正常完整周期 // 正常完整周期
double rent = calculateRent(payCycleMonths, params, chargeType); String rent = calculateRent(payCycleMonths, params, chargeType);
bill.put(fieldDisplayNameService.getDisplayName("租费"), String.valueOf(rent)); bill.put(fieldDisplayNameService.getDisplayName("租费"), rent);
bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(periodEnd.getTime())); bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(periodEnd.getTime()));
} else { } else {
// 最后一期:不足一个缴费周期 // 最后一期:不足一个缴费周期
int realMonths = dateUtil.betweenMonthByTwoCalendar(tempStart, endTime); int realMonths = dateUtil.betweenMonthByTwoCalendar(tempStart, endTime);
double rent = calculateRent(realMonths, params, chargeType); String rent = calculateRent(realMonths, params, chargeType);
Calendar realEnd = (Calendar) endTime.clone(); Calendar realEnd = (Calendar) endTime.clone();
realEnd.add(Calendar.DATE, -1); realEnd.add(Calendar.DATE, -1);
bill.put(fieldDisplayNameService.getDisplayName("租费"), String.valueOf(rent)); bill.put(fieldDisplayNameService.getDisplayName("租费"), rent);
bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime())); bill.put(fieldDisplayNameService.getDisplayName("结束日期"), sdf.format(realEnd.getTime()));
} }
@@ -255,24 +263,44 @@ public class LeaseBillUtil {
* @param months 计费月数 * @param months 计费月数
* @param params 表单参数 * @param params 表单参数
* @param chargeType 计费方式 * @param chargeType 计费方式
* @return 计算后租金金额 * @return 计算后租金金额保留2位小数
*/ */
private double calculateRent(int months, JSONObject params, String chargeType) { private String calculateRent(int months, JSONObject params, String chargeType) {
double unitPrice = 0; BigDecimal rent = BigDecimal.ZERO;
boolean isAreaCharge = "面积计费".equals(chargeType); boolean isAreaCharge = "面积计费".equals(chargeType);
boolean isFixedRent = "固定租金".equals(chargeType); boolean isFixedRent = "固定租金".equals(chargeType);
if (isAreaCharge) { if (isAreaCharge) {
// 面积计费:租金 = 面积 × 每平单价 // 面积计费:租金 = 面积 × 每平单价
double area = Double.parseDouble(params.getString("mj")); BigDecimal area = parseBigDecimal(params.getString("mj"));
double pricePerArea = dateUtil.stringToNum(params.getString("mjzj")); BigDecimal pricePerArea = parseBigDecimal(params.getString("mjzj"));
unitPrice = area * pricePerArea; rent = area.multiply(pricePerArea);
} else if (isFixedRent) { } else if (isFixedRent) {
// 固定租金:直接取固定金额 // 固定租金:直接取固定金额
unitPrice = dateUtil.stringToNum(params.getString("gdzj")); rent = parseBigDecimal(params.getString("gdzj"));
} }
// 固定租金不乘月数,其他计费方式 × 月数 // 固定租金不乘月数,其他计费方式 × 月数
return isFixedRent ? unitPrice : unitPrice * months; if (!isFixedRent) {
rent = rent.multiply(new BigDecimal(months));
}
// 保留2位小数四舍五入
return rent.setScale(MONEY_SCALE, RoundingMode.HALF_UP).toString();
} }
}
/**
* 将字符串解析为BigDecimal处理逗号分隔符
*
* @param str 数字字符串(可能包含逗号分隔符)
* @return BigDecimal对象
*/
private BigDecimal parseBigDecimal(String str) {
if (str == null || str.trim().isEmpty()) {
return BigDecimal.ZERO;
}
// 移除逗号分隔符
String cleanStr = str.replace(",", "").trim();
return new BigDecimal(cleanStr);
}
}