BMS计费单据审核计费流水周期开始时间和结束时间的生成

This commit is contained in:
秦鸿展
2026-03-02 13:42:36 +08:00
parent 744385db91
commit 8e51377db1
2 changed files with 173 additions and 39 deletions
@@ -147,15 +147,16 @@ public class BusinessDocumentApplicationService {
if (ObjectUtil.isNull(loginUser)) { if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT); throw new DigitalLogisticsException(UserError.TIMEOUT);
} }
//先设置组织信息,因为handleDate方法中需要使用topOrganizationId
businessDocumentDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
businessDocumentDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
businessDocumentDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
//校验使用的表单是否必填校验 //校验使用的表单是否必填校验
checkDoucumentType(businessDocumentDO); checkDoucumentType(businessDocumentDO);
//处理数据 //处理数据
handleDate(businessDocumentDO); handleDate(businessDocumentDO);
businessDocumentDO.setDataSources(2); businessDocumentDO.setDataSources(2);
businessDocumentDO.setBusinessFlow(OrderSequence.getOrderCode("LS")); businessDocumentDO.setBusinessFlow(OrderSequence.getOrderCode("LS"));
businessDocumentDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
businessDocumentDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
businessDocumentDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
//调用费用计算,计算费用金额进行保存 //调用费用计算,计算费用金额进行保存
CostCalculationDTO costCalculationDTO = new CostCalculationDTO(); CostCalculationDTO costCalculationDTO = new CostCalculationDTO();
costCalculationDTO.setOriginalBusinessNum(businessDocumentDO.getOriginalBusinessNum()); costCalculationDTO.setOriginalBusinessNum(businessDocumentDO.getOriginalBusinessNum());
@@ -211,6 +212,13 @@ public class BusinessDocumentApplicationService {
* 处理数据 * 处理数据
*/ */
private void handleDate(BusinessDocumentDO businessDocumentDO) { private void handleDate(BusinessDocumentDO businessDocumentDO) {
//确保topOrganizationId已设置,如果为null则从登录用户获取
if (businessDocumentDO.getTopOrganizationId() == null) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNotNull(loginUser) && loginUser.getUserPo() != null) {
businessDocumentDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
}
}
if(businessDocumentDO.getOrganizationId() != null){ if(businessDocumentDO.getOrganizationId() != null){
//获取组织信息 //获取组织信息
AjaxResult ajaxResult = productServiceFeign.getOrganizationInfo(businessDocumentDO.getOrganizationId()); AjaxResult ajaxResult = productServiceFeign.getOrganizationInfo(businessDocumentDO.getOrganizationId());
@@ -222,11 +230,23 @@ public class BusinessDocumentApplicationService {
throw new ServiceException("组织信息未找到"); throw new ServiceException("组织信息未找到");
} }
businessDocumentDO.setOrganizationName(organizationPo.getOrganizationName()); businessDocumentDO.setOrganizationName(organizationPo.getOrganizationName());
businessDocumentDO.setTopOrganizationId(organizationPo.getParentOrganizationId()); Long parentOrganizationId = organizationPo.getParentOrganizationId();
if(organizationPo.getParentOrganizationId()==0){ if(parentOrganizationId != null && parentOrganizationId != 0){
businessDocumentDO.setTopOrganizationId(parentOrganizationId);
} else {
//如果parentOrganizationId为null或0,使用organizationId作为topOrganizationId
businessDocumentDO.setTopOrganizationId(businessDocumentDO.getOrganizationId()); businessDocumentDO.setTopOrganizationId(businessDocumentDO.getOrganizationId());
} }
} }
//再次确保topOrganizationId不为null(在设置组织信息后)
if (businessDocumentDO.getTopOrganizationId() == null) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNotNull(loginUser) && loginUser.getUserPo() != null) {
businessDocumentDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
} else {
throw new ServiceException("topOrganizationId不能为空,请确保已登录或传入有效的组织信息");
}
}
if(StringUtils.isNotEmpty(businessDocumentDO.getProjectCode())){ if(StringUtils.isNotEmpty(businessDocumentDO.getProjectCode())){
AjaxResult ajaxResult = systemServiceFeign.getProjectByCode(businessDocumentDO.getProjectCode()); AjaxResult ajaxResult = systemServiceFeign.getProjectByCode(businessDocumentDO.getProjectCode());
if(!"200".equals(String.valueOf(ajaxResult.get("code")))) { if(!"200".equals(String.valueOf(ajaxResult.get("code")))) {
@@ -304,7 +324,18 @@ public class BusinessDocumentApplicationService {
} }
//根据费用科目code查询费用信息,并赋值 //根据费用科目code查询费用信息,并赋值
if(StringUtils.isNotEmpty(businessDocumentDO.getSecondSubjectCode())){ if(StringUtils.isNotEmpty(businessDocumentDO.getSecondSubjectCode())){
AjaxResult ajaxResult = systemServiceFeign.getSubInfoByCode2(businessDocumentDO.getSecondSubjectCode(),businessDocumentDO.getTopOrganizationId()); //确保topOrganizationId不为null,如果为null则从登录用户获取
Long topOrganizationId = businessDocumentDO.getTopOrganizationId();
if (topOrganizationId == null) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNotNull(loginUser) && loginUser.getUserPo() != null) {
topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
businessDocumentDO.setTopOrganizationId(topOrganizationId);
} else {
throw new ServiceException("topOrganizationId不能为空");
}
}
AjaxResult ajaxResult = systemServiceFeign.getSubInfoByCode2(businessDocumentDO.getSecondSubjectCode(), topOrganizationId);
if("200".equals(String.valueOf(ajaxResult.get("code")))){ if("200".equals(String.valueOf(ajaxResult.get("code")))){
ExpenseAccountPO expenseAccountPO = JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), ExpenseAccountPO.class); ExpenseAccountPO expenseAccountPO = JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), ExpenseAccountPO.class);
if(null == expenseAccountPO || expenseAccountPO.getExpenseAccountId()==null){ if(null == expenseAccountPO || expenseAccountPO.getExpenseAccountId()==null){
@@ -361,6 +392,19 @@ public class BusinessDocumentApplicationService {
if(businessDocumentPO.getDataSources()==1){ if(businessDocumentPO.getDataSources()==1){
throw new ServiceException("非手工录入数据,无法修改"); throw new ServiceException("非手工录入数据,无法修改");
} }
//确保组织信息已设置,因为handleDate方法中需要使用topOrganizationId
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNotNull(loginUser) && loginUser.getUserPo() != null) {
if (businessDocumentDO.getTopOrganizationId() == null) {
businessDocumentDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
}
if (businessDocumentDO.getOrganizationId() == null) {
businessDocumentDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
}
if (StringUtils.isEmpty(businessDocumentDO.getOrganizationName())) {
businessDocumentDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
}
}
//校验使用的表单是否必填校验 //校验使用的表单是否必填校验
checkDoucumentType(businessDocumentDO); checkDoucumentType(businessDocumentDO);
//处理数据 //处理数据
@@ -371,7 +371,15 @@ public class BillingStatementDomainService {
String[] ignroreFields = new String[]{"billingStatementId","dataSources","createBy","createByName","createTime","updateBy","updateByName","updateTime"}; String[] ignroreFields = new String[]{"billingStatementId","dataSources","createBy","createByName","createTime","updateBy","updateByName","updateTime"};
BeanUtils.copyProperties(businessDocumentPO,billingStatementDO,ignroreFields); BeanUtils.copyProperties(businessDocumentPO,billingStatementDO,ignroreFields);
billingStatementDO.setBusinessDocumentId(businessDocumentPO.getBusinessDocumentId()); billingStatementDO.setBusinessDocumentId(businessDocumentPO.getBusinessDocumentId());
billingStatementDO.setBusinessDate(businessDocumentPO.getCreateTime()); //设置业务日期:优先使用计费时间,如果没有则使用创建时间,如果还没有则使用当前日期
Date businessDate = businessDocumentPO.getBillingTime();
if (businessDate == null) {
businessDate = businessDocumentPO.getCreateTime();
}
if (businessDate == null) {
businessDate = new Date();
}
billingStatementDO.setBusinessDate(businessDate);
billingStatementDO.setBillingAmount(businessDocumentPO.getBillAmount()); billingStatementDO.setBillingAmount(businessDocumentPO.getBillAmount());
billingStatementDO.setBillingState(1); billingStatementDO.setBillingState(1);
billingStatementDO.setDataSources(1); billingStatementDO.setDataSources(1);
@@ -394,6 +402,7 @@ public class BillingStatementDomainService {
private void handleData(BillingStatementDO billingStatementDO) { private void handleData(BillingStatementDO billingStatementDO) {
//查询合同信息,赋值合同周期信息 //查询合同信息,赋值合同周期信息
//优先通过合同编号获取合同信息 //优先通过合同编号获取合同信息
boolean cycleTimeSet = false;
if(StringUtils.isNotEmpty(billingStatementDO.getContractNumber())){ if(StringUtils.isNotEmpty(billingStatementDO.getContractNumber())){
AjaxResult ajaxResult = systemServiceFeign.getInfoByCode(billingStatementDO.getContractNumber()); AjaxResult ajaxResult = systemServiceFeign.getInfoByCode(billingStatementDO.getContractNumber());
if("200".equals(String.valueOf(ajaxResult.get("code")))){ if("200".equals(String.valueOf(ajaxResult.get("code")))){
@@ -402,7 +411,44 @@ public class BillingStatementDomainService {
//根据合同判断计费流水的周期开始日期和周期结束日期 //根据合同判断计费流水的周期开始日期和周期结束日期
setCycleTimeByContract(billingStatementDO, contractManagePO); setCycleTimeByContract(billingStatementDO, contractManagePO);
billingStatementDO.setContractType(contractManagePO.getContractType()); billingStatementDO.setContractType(contractManagePO.getContractType());
//检查周期时间是否已设置
if(billingStatementDO.getCycleBeginTime() != null && billingStatementDO.getCycleEndTime() != null){
cycleTimeSet = true;
log.info("根据合同设置周期时间成功,合同编号:{},出账日:{},周期开始:{},周期结束:{}",
billingStatementDO.getContractNumber(),
contractManagePO.getPaymentDate(),
billingStatementDO.getCycleBeginTime(),
billingStatementDO.getCycleEndTime());
} else {
log.warn("根据合同设置周期时间失败,合同编号:{},出账日:{}",
billingStatementDO.getContractNumber(),
contractManagePO.getPaymentDate());
} }
} else {
log.warn("合同信息为空,合同编号:{}", billingStatementDO.getContractNumber());
}
} else {
log.warn("查询合同信息失败,合同编号:{},返回码:{}",
billingStatementDO.getContractNumber(),
ajaxResult.get("code"));
}
} else {
log.warn("合同编号为空,无法查询合同信息");
}
//如果周期时间未设置,使用业务日期作为默认值
if(!cycleTimeSet){
Date businessDate = billingStatementDO.getBusinessDate();
if(businessDate != null){
billingStatementDO.setCycleBeginTime(businessDate);
billingStatementDO.setCycleEndTime(businessDate);
log.warn("周期时间未设置,使用业务日期作为默认值:{}", businessDate);
} else {
//如果业务日期也为null,使用当前日期
Date now = new Date();
billingStatementDO.setBusinessDate(now);
billingStatementDO.setCycleBeginTime(now);
billingStatementDO.setCycleEndTime(now);
log.warn("业务日期为空,使用当前日期作为默认值:{}", now);
} }
} }
//根据结算对象获取收支类型 //根据结算对象获取收支类型
@@ -420,47 +466,91 @@ public class BillingStatementDomainService {
/** /**
* 根据合同判断计费流水的周期开始日期和周期结束日期 * 根据合同判断计费流水的周期开始日期和周期结束日期
* (1)周期开始日期:根据合同明细的计费属性判断 * 统一使用出账日来计算周期时间:
* - 实时计费、按天计费:周期开始日期 = 业务日期 * 1)周期开始日期:上个月的出账日
* - 按账期计费:周期开始日期 = 业务日期 * 2)周期结束日期:本月出账日的前一天
* - 按周计费:周期开始日期 = 业务日期 * 例如:出账日是10号,业务日期是3月15号,则周期为2月10号到3月9号
* (2)周期结束日期:根据合同明细的计费属性判断
* - 实时计费、按天计费:周期结束日期 = 业务日期
* - 按账期计费:周期结束日期 = 合同的出账日期(paymentDate
* - 按周计费:周期结束日期 = 业务日期往后推一周
* @param billingStatementDO 计费流水对象 * @param billingStatementDO 计费流水对象
* @param contractManagePO 合同管理对象 * @param contractManagePO 合同管理对象
*/ */
private void setCycleTimeByContract(BillingStatementDO billingStatementDO, ContractManagePO contractManagePO) { private void setCycleTimeByContract(BillingStatementDO billingStatementDO, ContractManagePO contractManagePO) {
//取值合同详情,对比费用科目,取值计费周期
if(contractManagePO.getContractManageDetailPOList()!=null && contractManagePO.getContractManageDetailPOList().size()>0){
List<ContractManageDetailPO> contractManageDetailPOList = contractManagePO.getContractManageDetailPOList();
String subjectCode = !StringUtils.isNotEmpty(billingStatementDO.getSecondSubjectCode()) ? billingStatementDO.getFirstSubjectCode() : billingStatementDO.getSecondSubjectCode();
Date cycleBeginTime = null;
Date cycleEndTime = null;
for (ContractManageDetailPO contractManageDetailPO : contractManageDetailPOList) {
String subjectCodeContract = !StringUtils.isNotEmpty(contractManageDetailPO.getSecondSubjectCode()) ? contractManageDetailPO.getFirstSubjectCode() : contractManageDetailPO.getSecondSubjectCode();
if(subjectCodeContract.equals(subjectCode)){
Date businessDate = billingStatementDO.getBusinessDate(); Date businessDate = billingStatementDO.getBusinessDate();
//根据不同类型获取计费周期 //确保业务日期不为null
if(ObjectUtil.equal(contractManageDetailPO.getBillingAttributesCode(),"1") || ObjectUtil.equal(contractManageDetailPO.getBillingAttributesCode(),"4")){ if (businessDate == null) {
//实时计费、按天计费,赋值为当天 businessDate = new Date();
cycleBeginTime = businessDate; billingStatementDO.setBusinessDate(businessDate);
cycleEndTime = businessDate; log.warn("业务日期为空,使用当前日期:{}", businessDate);
}else if(ObjectUtil.equal(contractManageDetailPO.getBillingAttributesCode(),"2")){
//按账期计费
cycleBeginTime = businessDate;
cycleEndTime = contractManagePO.getPaymentDate();
}else if(ObjectUtil.equal(contractManageDetailPO.getBillingAttributesCode(),"3")){
//按周计费,用businessDate往后推一周的日期
cycleBeginTime = businessDate;
cycleEndTime = DateUtil.offsetWeek(businessDate,1);
} }
break;
//统一根据出账日计算周期时间:开始时间为上个月的出账日,结束时间为本月出账日的前一天
Date paymentDate = contractManagePO.getPaymentDate();
if (paymentDate != null) {
// 获取出账日的"日"部分(1-31
// 注意:由于ContractManagePO中paymentDate的@JsonFormat设置为"d"(只显示日),
// 在反序列化时可能被解析为1970年1月1日,需要特殊处理
int paymentDay;
// 检查是否是1970年1月1日(说明存储的实际上是"日"而不是完整日期)
if (DateUtil.year(paymentDate) == 1970 && DateUtil.month(paymentDate) == 0) {
// 这种情况下,需要从时间戳中提取天数
// 如果数据库中存储的是"10"(表示10号),时间戳可能是10毫秒
long timeInMillis = paymentDate.getTime();
// 如果时间戳很小(小于一天的毫秒数),说明存储的就是天数
if (timeInMillis > 0 && timeInMillis < 24 * 60 * 60 * 1000) {
// 时间戳就是天数(比如10表示10号)
paymentDay = (int)timeInMillis;
} else {
// 否则尝试从日期中提取天数(如果是1970-01-11,则提取11
paymentDay = DateUtil.dayOfMonth(paymentDate);
// 如果提取的是1(1970-01-01),尝试从时间戳计算天数
if (paymentDay == 1) {
// 计算从1970-01-01 00:00:00 UTC开始的天数
long daysFrom1970 = timeInMillis / (24 * 60 * 60 * 1000);
if (daysFrom1970 >= 1 && daysFrom1970 <= 31) {
paymentDay = (int)daysFrom1970;
} else {
// 尝试计算从1970-01-01 00:00:00 CST开始的天数
// 1970-01-01 00:00:00 CST = 1970-01-01 08:00:00 UTC = -28800000毫秒
long cstBaseTime = -8 * 60 * 60 * 1000L; // CST基准时间
long daysFromCST = (timeInMillis - cstBaseTime) / (24 * 60 * 60 * 1000);
if (daysFromCST >= 1 && daysFromCST <= 31) {
paymentDay = (int)daysFromCST;
} }
} }
}
}
log.info("检测到1970年日期,从时间戳提取出账日:时间戳={},从日期提取={},最终出账日={}",
timeInMillis, DateUtil.dayOfMonth(paymentDate), paymentDay);
} else {
// 正常情况,从日期中提取"日"部分
paymentDay = DateUtil.dayOfMonth(paymentDate);
}
// 确保paymentDay在有效范围内(1-31
if (paymentDay < 1 || paymentDay > 31) {
log.warn("出账日无效:{},使用业务日期的日作为默认值", paymentDay);
paymentDay = DateUtil.dayOfMonth(businessDate);
}
// 使用业务日期来计算周期时间,而不是当前日期
// 计算业务日期所在月的出账日
Date currentMonthPaymentDate = DateUtil.beginOfMonth(businessDate);
currentMonthPaymentDate = DateUtil.offsetDay(currentMonthPaymentDate, paymentDay - 1);
// 结束时间:本月出账日的前一天
Date cycleEndTime = DateUtil.offsetDay(currentMonthPaymentDate, -1);
// 开始时间:上个月的出账日
Date cycleBeginTime = DateUtil.offsetMonth(currentMonthPaymentDate, -1);
billingStatementDO.setCycleBeginTime(cycleBeginTime); billingStatementDO.setCycleBeginTime(cycleBeginTime);
billingStatementDO.setCycleEndTime(cycleEndTime); billingStatementDO.setCycleEndTime(cycleEndTime);
log.info("计算周期时间 - 业务日期:{},出账日原始值:{},出账日(日):{},本月出账日:{},周期开始:{},周期结束:{}",
businessDate, paymentDate, paymentDay, currentMonthPaymentDate, cycleBeginTime, cycleEndTime);
} else {
// 如果没有出账日,使用业务日期作为默认值
billingStatementDO.setCycleBeginTime(businessDate);
billingStatementDO.setCycleEndTime(businessDate);
log.warn("合同出账日为空,使用业务日期作为默认值:{}", businessDate);
} }
} }