Files
AssetsTenantServer/src/main/java/com/seeyon/apps/assetstenant/bill/BillService.java

350 lines
20 KiB
Java
Raw Normal View History

2026-05-06 16:04:39 +08:00
package com.seeyon.apps.assetstenant.bill;
2026-06-07 18:17:12 +08:00
import cn.hutool.log.Log;
2026-05-06 16:04:39 +08:00
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.assetstenant.assets.AssetsService;
import com.seeyon.apps.assetstenant.assets.OaAssetsVo;
import com.seeyon.apps.assetstenant.config.AssetsTenantConfigProvider;
2026-06-07 18:17:12 +08:00
import com.seeyon.apps.assetstenant.constants.AssetsTenantConstants;
import com.seeyon.apps.assetstenant.contract.ContractPayBaseInfo;
2026-05-06 16:04:39 +08:00
import com.seeyon.apps.assetstenant.contract.ContractService;
2026-06-07 18:17:12 +08:00
import com.seeyon.apps.assetstenant.contract.OaContractDetailVo;
import com.seeyon.apps.assetstenant.flow.FlowCreateService;
2026-05-06 16:04:39 +08:00
import com.seeyon.apps.assetstenant.po.PageQueryVo;
2026-06-07 18:17:12 +08:00
import com.seeyon.cap4.form.api.FormApi4Cap4;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormFieldBean;
2026-05-06 16:04:39 +08:00
import com.seeyon.cap4.form.bean.FormTableBean;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.exceptions.BusinessException;
2026-06-07 18:17:12 +08:00
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
2026-05-06 16:04:39 +08:00
import com.seeyon.utils.form.*;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
2026-06-07 18:17:12 +08:00
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
2026-05-06 16:04:39 +08:00
public class BillService {
2026-06-07 18:17:12 +08:00
private static final Log log = Log.get(BillService.class);
2026-05-06 16:04:39 +08:00
private AssetsTenantConfigProvider configProvider = (AssetsTenantConfigProvider) AppContext.getBean("assetsTenantConfigProvider");
private ContractService contractService = (ContractService) AppContext.getBean("contractService");
private AssetsService assetsService = (AssetsService) AppContext.getBean("assetsService");
2026-06-07 18:17:12 +08:00
private FlowCreateService flowCreateService = (FlowCreateService) AppContext.getBean("flowCreateService");
private OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
2026-05-06 16:04:39 +08:00
private String getFormNo() {
2026-06-07 18:17:12 +08:00
return configProvider.getBizConfigByKey(AssetsTenantConstants.CONTRACTBILLFORMNO);
2026-05-06 16:04:39 +08:00
}
private TableContext getTableContext() throws BusinessException {
TableContext tableContext = FormTableExecutor.master(getFormNo());
return tableContext;
}
2026-06-07 18:17:12 +08:00
private String getStringValue(Map<String, Object> fieldsMap, String key) {
2026-05-06 16:04:39 +08:00
Object o = fieldsMap.get(key);
2026-06-07 18:17:12 +08:00
if (o == null) {
2026-05-06 16:04:39 +08:00
return null;
}
return o + "";
}
private List<FormWhereCondition> buildConditions(JSONObject params, FormTableBean formTableBean) {
List<FormWhereCondition> conditions = new ArrayList<>();
2026-06-07 18:17:12 +08:00
if (StringUtils.isNotBlank(params.getString("cusNo"))) {
2026-05-06 16:04:39 +08:00
conditions.add(FormWhereCondition.build().display("承租方编号").value(params.getString("cusNo")));
}
2026-06-07 18:17:12 +08:00
if (StringUtils.isNotBlank(params.getString("billNo"))) {
conditions.add(FormWhereCondition.build().display("账单-账单明细编号").value(params.getString("billNo")));
2026-05-06 16:04:39 +08:00
}
2026-06-07 18:17:12 +08:00
if(StringUtils.isNotBlank(params.getString("contractNo"))) {
conditions.add(FormWhereCondition.build().display("合同编号").value(params.getString("contractNo")));
}
if (StringUtils.isNotBlank(params.getString("billStatus"))) {
if ("已缴费".equals(params.getString("billStatus"))) {
2026-05-06 16:04:39 +08:00
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").clauseFactor(ClauseFactor.NOT_NULL));
2026-06-07 18:17:12 +08:00
} else {
2026-05-06 16:04:39 +08:00
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").clauseFactor(ClauseFactor.NULL).startWithBracket(true).concatFactor(ClauseFactor.OR));
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").value(EnumMapUtils.getEnumItemValueByDisplayValue(formTableBean, "账单-收款结果反馈", "未收款")).endWithBracket(true));
}
}
return conditions;
}
2026-06-07 18:17:12 +08:00
public List<BillVo> queryAllContractBill(List<FormWhereCondition> conditions) throws Exception {
2026-05-06 16:04:39 +08:00
TableContext tableContext = getTableContext();
2026-06-07 18:17:12 +08:00
List<FormColumn> datas = FormTableExecutor.query(tableContext, null, conditions, true);
2026-05-06 16:04:39 +08:00
List<BillVo> vos = new ArrayList<>();
2026-06-07 18:17:12 +08:00
if (datas.size() > 0) {
for (FormColumn data : datas) {
Map<String, Object> map = data.getFieldsMap();
2026-05-06 16:04:39 +08:00
BillVo billVo = new BillVo();
fillVo(map, billVo);
vos.add(billVo);
}
}
return vos;
}
2026-06-07 18:17:12 +08:00
public List<ContractPayBaseInfo> queryContractPayBaseInfoList(String contractNo) throws BusinessException {
List<ContractPayBaseInfo> contractPayBaseInfoList = new ArrayList<>();
String formNo = configProvider.getBizConfigByKey(AssetsTenantConstants.BILLCREATEFORMNO);
List<FormWhereCondition> conditions = new ArrayList<>();
conditions.add(FormWhereCondition.build().display("合同编号").value(contractNo));
TableContext master = FormTableExecutor.master(formNo);
List<FormColumn> formColumns = FormTableExecutor.query(master, null, conditions, true);
if(formColumns == null || formColumns.size() <= 0){
return contractPayBaseInfoList;
}
for (FormColumn formColumn : formColumns) {
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
ContractPayBaseInfo baseInfo = new ContractPayBaseInfo();
baseInfo.setContractNo(contractNo);
baseInfo.setAssetsName(getStringValue(fieldsMap, "资产名称"));
baseInfo.setAssetsNo(getStringValue(fieldsMap,"资产编号"));
baseInfo.setTotalRentFee(getStringValue(fieldsMap,"本账单金额"));
Integer totalPeriod = contractService.countTotalPeriod(contractNo);
baseInfo.setTotalTermNum(totalPeriod + "");
Integer countPaidTermNum = countPaidTermNum(baseInfo.getAssetsNo(), baseInfo.getContractNo());
baseInfo.setPaidTermNum(countPaidTermNum + "");
JSONObject param = new JSONObject();
param.put("contractNo", contractNo);
try {
OaContractDetailVo detailVo = contractService.queryContractDetail(param);
baseInfo.setDeposit(detailVo.getDeposit());
}catch (Exception e) {
}
contractPayBaseInfoList.add(baseInfo);
}
return contractPayBaseInfoList;
}
public Integer countPaidTermNum(String assetsNo,String contractNo) throws BusinessException {
TableContext tableContext = getTableContext();
List<FormWhereCondition> conditions = new ArrayList<>();
conditions.add(FormWhereCondition.build().display("资产编号").value(assetsNo));
conditions.add(FormWhereCondition.build().display("合同编号").value(contractNo));
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(),"收款结果反馈", "已结清")));
conditions.add(FormWhereCondition.build().display("账单类型").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(),"账单类型", "租金")));
Long count = FormTableExecutor.count(tableContext, null, conditions);
return count.intValue();
}
2026-05-06 16:04:39 +08:00
public Integer countUnpayRentBills(JSONObject params) throws Exception {
TableContext tableContext = getTableContext();
2026-06-07 18:17:12 +08:00
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
2026-05-06 16:04:39 +08:00
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").clauseFactor(ClauseFactor.NULL).startWithBracket(true).concatFactor(ClauseFactor.OR));
2026-06-07 18:17:12 +08:00
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(), "账单-收款结果反馈", "未收款")).endWithBracket(true));
Long count = FormTableExecutor.count(tableContext, null, conditions);
2026-05-06 16:04:39 +08:00
return count.intValue();
}
public PageQueryVo pageQueryContractBill(JSONObject params) throws Exception {
TableContext tableContext = getTableContext();
2026-06-07 18:17:12 +08:00
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
2026-05-06 16:04:39 +08:00
Integer pageNo = params.getInteger("pageNo") == null ? 1 : params.getInteger("pageNo");
Integer pageSize = params.getInteger("pageSize") == null ? 10 : params.getInteger("pageSize");
PageQueryVo<BillVo> pageQueryVo = new PageQueryVo();
2026-06-07 18:17:12 +08:00
List<FormColumn> datas = FormTableExecutor.pageQuery(tableContext, null, conditions, pageNo, pageSize, true);
2026-05-06 16:04:39 +08:00
List<BillVo> vos = new ArrayList<>();
2026-06-07 18:17:12 +08:00
Long count = FormTableExecutor.count(tableContext, null, conditions);
if (datas.size() > 0) {
for (FormColumn data : datas) {
Map<String, Object> map = data.getFieldsMap();
2026-05-06 16:04:39 +08:00
BillVo billVo = new BillVo();
fillVo(map, billVo);
vos.add(billVo);
}
pageQueryVo.setDatas(vos);
pageQueryVo.setTotalCount(count);
}
return pageQueryVo;
}
public BillVo queryOne(JSONObject params) throws Exception {
TableContext tableContext = getTableContext();
2026-06-07 18:17:12 +08:00
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
FormColumn formColumn = FormTableExecutor.queryOne(tableContext, conditions, true);
if (formColumn == null) {
2026-05-06 16:04:39 +08:00
return null;
}
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
BillVo billVo = new BillVo();
fillVo(fieldsMap, billVo);
return billVo;
}
public void fillVo(Map<String, Object> fieldsMap, BillVo billVo) throws Exception {
2026-06-07 18:17:12 +08:00
billVo.setBillType(getStringValue(fieldsMap, "账单类型"));
billVo.setBillNo(getStringValue(fieldsMap, "账单-账单明细编号"));
String payStatus = fieldsMap.get("账单-收款结果反馈") == null ? "待缴费" : getStringValue(fieldsMap, "账单-收款结果反馈");
billVo.setBillStatus(payStatus);
billVo.setCusNo(getStringValue(fieldsMap, "承租方编号"));
billVo.setBillStartDate(getStringValue(fieldsMap, "账单-开始日期"));
billVo.setContractNo(getStringValue(fieldsMap, "合同编号"));
billVo.setBillPayEndDate(getStringValue(fieldsMap, "账单-当前缴费时限"));
billVo.setBillEndDate(getStringValue(fieldsMap, "账单-结束日期"));
String billName = buildBillName(fieldsMap, billVo);
billVo.setBillPayDate(getStringValue(fieldsMap, "账单-实际收款时间"));
billVo.setBillName(billName);
if(billVo.getBillTermNum() != null && 1 == billVo.getBillTermNum()) {
billVo.setDeposit(getDeposit(getStringValue(fieldsMap, "合同编号")));
2026-05-06 16:04:39 +08:00
}
2026-06-07 18:17:12 +08:00
if("租金".equals(billVo.getBillType())) {
BigDecimal bigDecimal = (BigDecimal) fieldsMap.get("账单-租费");
billVo.setBillAmount(bigDecimal == null ? null : bigDecimal.toString());
}else if("履约保证金".equals(billVo.getBillType())){
BigDecimal bigDecimal = (BigDecimal) fieldsMap.get("约定履约保证金");
billVo.setBillAmount(bigDecimal == null ? null : bigDecimal.toString());
}else if("违约金".equals(billVo.getBillType())){
BigDecimal bigDecimal = (BigDecimal) fieldsMap.get("应收违约金");
billVo.setBillAmount(bigDecimal == null ? null : bigDecimal.toString());
}else if("滞纳金".equals(billVo.getBillType())){
BigDecimal bigDecimal = (BigDecimal) fieldsMap.get("应收滞纳金");
billVo.setBillAmount(bigDecimal == null ? null : bigDecimal.toString());
}
}
private String getDeposit(String contractNo) throws Exception {
JSONObject params = new JSONObject();
params.put("contractNo", contractNo);
OaContractDetailVo oaContractVo = contractService.queryContractDetail(params);
return oaContractVo == null ? null : oaContractVo.getDeposit();
2026-05-06 16:04:39 +08:00
}
2026-06-07 18:17:12 +08:00
private String buildBillName(Map<String, Object> fieldsMap, BillVo billVo) throws Exception {
String contractNo = getStringValue(fieldsMap, "合同编号");
Integer termNum = contractService.queryContractPayPeriod(contractNo, getStringValue(fieldsMap, "账单-开始日期"));
billVo.setBillTermNum(termNum);
OaAssetsVo oaAssetsVo = assetsService.queryAssetsDetail(getStringValue(fieldsMap, "资产编号"));
2026-05-06 16:04:39 +08:00
String asssetsName = null;
2026-06-07 18:17:12 +08:00
if (oaAssetsVo != null) {
2026-05-06 16:04:39 +08:00
asssetsName = oaAssetsVo.getAssetsName();
}
String roomNo = fieldsMap.get("门牌号") == null ? "" : fieldsMap.get("门牌号") + "-";
2026-06-07 18:17:12 +08:00
return asssetsName + roomNo + termNum + "";
}
public void payCallBack(String billNo,String payDate) throws Exception {
// 1. 获取Bean + 非空校验
FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4");
if (formApi4Cap4 == null) {
throw new Exception("Spring容器中未找到formApi4Cap4 Bean");
}
// 2. 复用配置,避免重复查询
String templateCode = this.configProvider.getBizConfigByKey(AssetsTenantConstants.PAYMENT_REGISTRATION_TEMPLATECODE);
String appName = this.configProvider.getBizConfigByKey(AssetsTenantConstants.FORMAPPNAME);
// 3. 获取表单结构
FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(templateCode);
FormTableBean masterTableBean = cap4FormBean.getMasterTableBean();
String tableName = masterTableBean.getTableName();
List<FormTableBean> subTableBeanList = cap4FormBean.getSubTableBean();
FormTableBean subTableBean = null;
// 4. 获取子表名 + 非空校验
String subDbTableName = null;
for (FormTableBean tableBean : subTableBeanList) {
if ("租金收款明细".equals(tableBean.getDisplay())) {
subDbTableName = tableBean.getTableName();
subTableBean = tableBean;
break;
}
}
// 5. 构造数据结构(规范泛型)
Map<String, Object> mainFormData = new HashMap<>();
Map<String, List<Object>> subFormDataMap = new HashMap<>();
List<Object> subFormDataList = new ArrayList<>();
Map<String, Object> mainData = new HashMap<>();
mainFormData.put(tableName, mainData);
if (subDbTableName != null) {
log.info("明细表表名为: " + subDbTableName);
subFormDataMap.put(subDbTableName, subFormDataList);
}
// 6. 查询账单数据
List<FormWhereCondition> conditions = new ArrayList<>();
conditions.add(FormWhereCondition.build().display("账单-账单明细编号").value(billNo));
FormColumn formColumn = FormTableExecutor.queryOne(getTableContext(), conditions,false);
// 7. 主数据非空判断
if (formColumn == null || formColumn.getFieldsMap() == null) {
throw new Exception("根据账单编号:" + billNo + "未查询到账单数据");
}
Map<String, Object> fieldsMap = formColumn.getFieldsMap();
BigDecimal accountsReceivable = BigDecimal.ZERO;
// 初始化实际收款金额避免null
BigDecimal actualReceipts = BigDecimal.ZERO;
BigDecimal rate = new BigDecimal("0.994");
// 8. 组装子表数据
Map<String, Object> subTableRowData = new HashMap<>();
subTableRowData.put("账单-明细编号", fieldsMap.get("账单-账单明细编号"));
subTableRowData.put("账单-开始日期", df.format((Date)fieldsMap.get("账单-开始日期")));
subTableRowData.put("账单-结束日期", df.format((Date)fieldsMap.get("账单-结束日期")));
subTableRowData.put("账单-当期缴费期限", fieldsMap.get("账单-当前缴费时限"));
subTableRowData.put("账单-综合减免", fieldsMap.get("账单-减免金额") == null ? BigDecimal.ZERO : fieldsMap.get("账单-减免金额"));
subTableRowData.put("账单-租费递增", fieldsMap.get("账单-租费递增") == null ? BigDecimal.ZERO : fieldsMap.get("账单-租费递增"));
// 应收金额计算
BigDecimal receivable = (BigDecimal) fieldsMap.get("账单-应收租金");
if (receivable != null) {
accountsReceivable = accountsReceivable.add(receivable);
// 修复BigDecimal.setScale不生效问题
actualReceipts = accountsReceivable.multiply(rate).setScale(2, RoundingMode.HALF_UP);
}
subTableRowData.put("账单-应收租金", receivable);
subTableRowData.put("账单-未收租金", fieldsMap.get("账单-未收租金"));
subTableRowData.put("账单-本次收租金", receivable);
subTableRowData.put("账单-本次收款日期", payDate);
subTableRowData.put("账单-本次开票金额", receivable);
subTableRowData.put("账单-未开票金额", receivable);
subTableRowData.put("账单-资产编号", fieldsMap.get("资产编号"));
subTableRowData.put("账单-资产名称", fieldsMap.get("资产名称"));
FormFieldBean formFieldBean = subTableBean.getFieldBeanByDisplay("收款结果");
subTableRowData.put("账单-收款结果", EnumMapUtils.getEnumItemValueByEnumId("已结清",formFieldBean.getEnumId()));
subFormDataList.add(subTableRowData);
// 9. 获取合同信息 + 非空校验
String contractNo = (String) fieldsMap.get("合同编号");
mainData.put("合同名称", fieldsMap.get("合同名称"));
mainData.put("合同金额", fieldsMap.get("合同金额"));
mainData.put("签订单位", fieldsMap.get("签订单位"));
mainData.put("承租方类型", fieldsMap.get("承租方类型"));
mainData.put("承租方名称", fieldsMap.get("承租方"));
mainData.put("承租方编码", fieldsMap.get("承租方编号"));
mainData.put("租金_费项_文本",fieldsMap.get("账单类型"));
// 10. 经办人/部门信息(安全赋值)
String assetNo = (String) fieldsMap.get("资产编号");
Map<String, Object> assetsManagerInfo = this.assetsService.getAssetsManagerInfo(assetNo);
if (assetsManagerInfo != null && assetsManagerInfo.get("运营管理员") != null) {
String managerId = String.valueOf(assetsManagerInfo.get("运营管理员"));
try {
V3xOrgMember member = this.orgManager.getMemberById(Long.parseLong(managerId));
if (member != null) {
mainData.put("经办部门", member.getOrgDepartmentId());
mainData.put("经办单位", member.getOrgAccountId());
mainData.put("经办人员", managerId);
}
} catch (Exception e) {
log.warn("获取经办人信息失败", e);
}
}
// 11. 组装主表数据(线程安全日期)
TableContext receivePayFlowTableContext = FormTableExecutor.master(templateCode);
mainData.put("选择收款项", EnumMapUtils.getEnumItemValueByDisplayValue(receivePayFlowTableContext.getTableBean(), "收款项", "租金"));
mainData.put("经办日期", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
mainData.put("合同编号", contractNo);
mainData.put("本次收款金额", actualReceipts);
// 12. 启动流程
this.flowCreateService.flowStart("微信小程序支付完成收款登记",
mainFormData, subFormDataMap, appName, templateCode);
2026-05-06 16:04:39 +08:00
}
}