Files
AssetsTenantServer/src/main/java/com/seeyon/apps/assetstenant/bill/BillService.java
2026-06-10 10:36:43 +08:00

350 lines
20 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.seeyon.apps.assetstenant.bill;
import cn.hutool.log.Log;
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;
import com.seeyon.apps.assetstenant.constants.AssetsTenantConstants;
import com.seeyon.apps.assetstenant.contract.ContractPayBaseInfo;
import com.seeyon.apps.assetstenant.contract.ContractService;
import com.seeyon.apps.assetstenant.contract.OaContractDetailVo;
import com.seeyon.apps.assetstenant.flow.FlowCreateService;
import com.seeyon.apps.assetstenant.po.PageQueryVo;
import com.seeyon.cap4.form.api.FormApi4Cap4;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormFieldBean;
import com.seeyon.cap4.form.bean.FormTableBean;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.utils.form.*;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
public class BillService {
private static final Log log = Log.get(BillService.class);
private AssetsTenantConfigProvider configProvider = (AssetsTenantConfigProvider) AppContext.getBean("assetsTenantConfigProvider");
private ContractService contractService = (ContractService) AppContext.getBean("contractService");
private AssetsService assetsService = (AssetsService) AppContext.getBean("assetsService");
private FlowCreateService flowCreateService = (FlowCreateService) AppContext.getBean("flowCreateService");
private OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
private String getFormNo() {
return configProvider.getBizConfigByKey(AssetsTenantConstants.CONTRACTBILLFORMNO);
}
private TableContext getTableContext() throws BusinessException {
TableContext tableContext = FormTableExecutor.master(getFormNo());
return tableContext;
}
private String getStringValue(Map<String, Object> fieldsMap, String key) {
Object o = fieldsMap.get(key);
if (o == null) {
return null;
}
return o + "";
}
private List<FormWhereCondition> buildConditions(JSONObject params, FormTableBean formTableBean) {
List<FormWhereCondition> conditions = new ArrayList<>();
if (StringUtils.isNotBlank(params.getString("cusNo"))) {
conditions.add(FormWhereCondition.build().display("承租方编号").value(params.getString("cusNo")));
}
if (StringUtils.isNotBlank(params.getString("billNo"))) {
conditions.add(FormWhereCondition.build().display("账单-账单明细编号").value(params.getString("billNo")));
}
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"))) {
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").clauseFactor(ClauseFactor.NOT_NULL));
} else {
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;
}
public List<BillVo> queryAllContractBill(List<FormWhereCondition> conditions) throws Exception {
TableContext tableContext = getTableContext();
List<FormColumn> datas = FormTableExecutor.query(tableContext, null, conditions, true);
List<BillVo> vos = new ArrayList<>();
if (datas.size() > 0) {
for (FormColumn data : datas) {
Map<String, Object> map = data.getFieldsMap();
BillVo billVo = new BillVo();
fillVo(map, billVo);
vos.add(billVo);
}
}
return vos;
}
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();
}
public Integer countUnpayRentBills(JSONObject params) throws Exception {
TableContext tableContext = getTableContext();
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").clauseFactor(ClauseFactor.NULL).startWithBracket(true).concatFactor(ClauseFactor.OR));
conditions.add(FormWhereCondition.build().display("账单-收款结果反馈").value(EnumMapUtils.getEnumItemValueByDisplayValue(tableContext.getTableBean(), "账单-收款结果反馈", "未收款")).endWithBracket(true));
Long count = FormTableExecutor.count(tableContext, null, conditions);
return count.intValue();
}
public PageQueryVo pageQueryContractBill(JSONObject params) throws Exception {
TableContext tableContext = getTableContext();
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
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();
List<FormColumn> datas = FormTableExecutor.pageQuery(tableContext, null, conditions, pageNo, pageSize, true);
List<BillVo> vos = new ArrayList<>();
Long count = FormTableExecutor.count(tableContext, null, conditions);
if (datas.size() > 0) {
for (FormColumn data : datas) {
Map<String, Object> map = data.getFieldsMap();
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();
List<FormWhereCondition> conditions = buildConditions(params, tableContext.getTableBean());
FormColumn formColumn = FormTableExecutor.queryOne(tableContext, conditions, true);
if (formColumn == null) {
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 {
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, "合同编号")));
}
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();
}
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, "资产编号"));
String asssetsName = null;
if (oaAssetsVo != null) {
asssetsName = oaAssetsVo.getAssetsName();
}
String roomNo = fieldsMap.get("门牌号") == null ? "" : fieldsMap.get("门牌号") + "-";
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);
}
}