package com.java110.fee.convertOnce; import com.java110.core.factory.GenerateCodeFactory; import com.java110.core.log.LoggerFactory; import com.java110.core.smo.IComputeFeeSMO; import com.java110.dto.fee.FeeAttrDto; import com.java110.dto.fee.FeeConfigDto; import com.java110.dto.fee.FeeDto; import com.java110.dto.owner.OwnerDto; import com.java110.dto.payFee.PayFeeDetailRefreshFeeMonthDto; import com.java110.fee.dao.IPayFeeConfigV1ServiceDao; import com.java110.fee.dao.impl.PayFeeV1ServiceDaoImpl; import com.java110.intf.fee.*; import com.java110.po.fee.FeeAttrPo; import com.java110.po.fee.PayFeePo; import com.java110.po.payFeeRule.PayFeeRulePo; import com.java110.utils.util.Assert; import com.java110.utils.util.BeanConvertUtil; import com.java110.utils.util.DateUtil; import com.java110.utils.util.StringUtil; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 转换一次性费用 */ @Service public class CycleConvertOnceFeeImpl implements ICycleConvertOnceFee { private static Logger logger = LoggerFactory.getLogger(PayFeeV1ServiceDaoImpl.class); @Autowired private IFeeInnerServiceSMO feeInnerServiceSMOImpl; @Autowired private IPayFeeConfigV1InnerServiceSMO payFeeConfigV1InnerServiceSMOImpl; @Autowired private IPayFeeRuleV1InnerServiceSMO payFeeRuleV1InnerServiceSMOImpl; @Autowired private IPayFeeV1InnerServiceSMO payFeeV1InnerServiceSMOImpl; @Autowired private IFeeAttrInnerServiceSMO feeAttrInnerServiceSMOImpl; @Autowired private IPayFeeMonthInnerServiceSMO payFeeMonthInnerServiceSMOImpl; @Autowired private IComputeFeeSMO computeFeeSMOImpl; @Override public int convertPayFees(List payFeePos) { List tmpPayFeePos = new ArrayList<>(); for (PayFeePo tmpPayFeePo : payFeePos) { //todo 一次性费用 直接跳过 if (FeeDto.FEE_FLAG_ONCE.equals(tmpPayFeePo.getFeeFlag())) { continue; } tmpPayFeePos.add(tmpPayFeePo); } if (tmpPayFeePos.isEmpty()) { return 0; } //todo 业务处理 List payFeeRulePos = new ArrayList<>(); PayFeeRulePo tmpPayFeeRulePo = null; String curYearMonth = ""; for (PayFeePo tmpPayFeePo : payFeePos) { tmpPayFeeRulePo = BeanConvertUtil.covertBean(tmpPayFeePo, PayFeeRulePo.class); tmpPayFeeRulePo.setRuleId(GenerateCodeFactory.getGeneratorId("11")); curYearMonth = DateUtil.getFormatTimeStringB(DateUtil.getDateFromStringB(tmpPayFeePo.getEndTime())); tmpPayFeeRulePo.setCurYearMonth(curYearMonth); payFeeRulePos.add(tmpPayFeeRulePo); } if (payFeeRulePos.isEmpty()) { return 0; } //todo 保存规则 payFeeRuleV1InnerServiceSMOImpl.savePayFeeRules(payFeeRulePos); //todo 根据规则生成费用 rulesGeneratePayFees(payFeeRulePos); return 0; } @Override public int convertPayFee(PayFeePo payFeePo) { List payFeePos = new ArrayList<>(); payFeePos.add(payFeePo); return convertPayFees(payFeePos); } @Override public int covertCommunityPayFee(String communityId) { return 0; } @Override public int covertRuleIdsPayFee(List ruleIds) { return 0; } @Override public int rulesGeneratePayFees(List payFeeRulePos) { if (payFeeRulePos == null || payFeeRulePos.isEmpty()) { return 0; } for (PayFeeRulePo tmpPayFeeRulePo : payFeeRulePos) { try { //todo 单个费用处理 ruleGeneratePayFee(tmpPayFeeRulePo); } catch (Exception e) { logger.error("处理异常 ruleId" + tmpPayFeeRulePo.getRuleId(), e); } } return payFeeRulePos.size(); } /** * @param tmpPayFeeRulePo */ public int ruleGeneratePayFee(PayFeeRulePo tmpPayFeeRulePo) { //todo 查询费用项信息 FeeConfigDto feeConfigDto = new FeeConfigDto(); feeConfigDto.setConfigId(tmpPayFeeRulePo.getConfigId()); feeConfigDto.setCommunityId(tmpPayFeeRulePo.getCommunityId()); List feeConfigDtos = payFeeConfigV1InnerServiceSMOImpl.queryPayFeeConfigs(feeConfigDto); Assert.listOnlyOne(feeConfigDtos, "费用项不存在,configId=" + tmpPayFeeRulePo.getConfigId()); //todo 计算目标 结束时间 Date targetEndTime = computeTargetEndTime(tmpPayFeeRulePo, feeConfigDtos.get(0)); //todo 创建 pay_fee 和 attrs 数据 List tmpPayFeePos = new ArrayList<>(); List tmpFeeAttrPos = new ArrayList<>(); FeeDto feeDto = new FeeDto(); feeDto.setPayerObjType(tmpPayFeeRulePo.getPayerObjType()); feeDto.setCommunityId(tmpPayFeeRulePo.getCommunityId()); feeDto.setPayerObjId(tmpPayFeeRulePo.getPayerObjId()); OwnerDto ownerDto = computeFeeSMOImpl.getFeeOwnerDto(feeDto); String payerObjName = computeFeeSMOImpl.getFeeObjName(feeDto); Date startTime = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getCurYearMonth()); Date endTime = null; //todo 没到时间 if (startTime.getTime() >= targetEndTime.getTime()) { return 0; } do { endTime = DateUtil.getNextMonthFirstDate(startTime); if (endTime.getTime() >= targetEndTime.getTime()) { endTime = targetEndTime; } //todo 生成 费用 doGeneratorPayFee(tmpPayFeeRulePo, startTime, endTime, feeConfigDtos.get(0), tmpPayFeePos, tmpFeeAttrPos, ownerDto, payerObjName); startTime = endTime; } while (endTime.getTime() < targetEndTime.getTime()); int saveFlag = 0; if (!tmpPayFeePos.isEmpty()) { saveFlag = saveFeeAndAttrs(tmpPayFeePos, tmpFeeAttrPos); } //todo 修改pay_fee_rule 的CurYearMonth PayFeeRulePo payFeeRulePo = new PayFeeRulePo(); payFeeRulePo.setRuleId(tmpPayFeeRulePo.getRuleId()); payFeeRulePo.setCurYearMonth(DateUtil.getFormatTimeStringB(endTime)); payFeeRulePo.setCommunityId(tmpPayFeeRulePo.getCommunityId()); payFeeRuleV1InnerServiceSMOImpl.updatePayFeeRule(payFeeRulePo); return saveFlag; } private void doGeneratorPayFee(PayFeeRulePo tmpPayFeeRulePo, Date startTime, Date endTime, FeeConfigDto feeConfigDto, List tmpPayFeePos, List tmpFeeAttrPos, OwnerDto ownerDto, String payerObjName) { PayFeePo payFeePo = BeanConvertUtil.covertBean(tmpPayFeeRulePo, PayFeePo.class); payFeePo.setFeeId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_feeId)); payFeePo.setFeeFlag(FeeDto.FEE_FLAG_ONCE); payFeePo.setStartTime(DateUtil.getFormatTimeStringB(startTime)); payFeePo.setEndTime(DateUtil.getFormatTimeStringB(startTime)); payFeePo.setRuleId(tmpPayFeeRulePo.getRuleId()); tmpPayFeePos.add(payFeePo); tmpFeeAttrPos.add(addFeeAttr(payFeePo, FeeAttrDto.SPEC_CD_ONCE_FEE_DEADLINE_TIME, DateUtil.getFormatTimeStringB(endTime))); if (ownerDto != null) { tmpFeeAttrPos.add(addFeeAttr(payFeePo, FeeAttrDto.SPEC_CD_OWNER_ID, ownerDto.getOwnerId())); tmpFeeAttrPos.add(addFeeAttr(payFeePo, FeeAttrDto.SPEC_CD_OWNER_LINK, ownerDto.getLink())); tmpFeeAttrPos.add(addFeeAttr(payFeePo, FeeAttrDto.SPEC_CD_OWNER_NAME, ownerDto.getName())); } //todo 付费对象名称 tmpFeeAttrPos.add(addFeeAttr(payFeePo, FeeAttrDto.SPEC_CD_PAY_OBJECT_NAME, payerObjName)); } private FeeAttrPo addFeeAttr(PayFeePo payFeePo, String specCd, String value) { FeeAttrPo feeAttrPo = new FeeAttrPo(); feeAttrPo.setCommunityId(payFeePo.getCommunityId()); feeAttrPo.setSpecCd(specCd); feeAttrPo.setValue(value); feeAttrPo.setFeeId(payFeePo.getFeeId()); feeAttrPo.setAttrId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_attrId, true)); return feeAttrPo; } private int saveFeeAndAttrs(List feePos, List feeAttrsPos) { if (feePos == null || feePos.isEmpty()) { return 1; } int flag = feeInnerServiceSMOImpl.saveFee(feePos); if (flag < 1) { return flag; } flag = feeAttrInnerServiceSMOImpl.saveFeeAttrs(feeAttrsPos); // todo 这里异步的方式计算 月数据 和欠费数据 List feeIds = new ArrayList<>(); for (PayFeePo feePo : feePos) { feeIds.add(feePo.getFeeId()); } PayFeeDetailRefreshFeeMonthDto payFeeDetailRefreshFeeMonthDto = new PayFeeDetailRefreshFeeMonthDto(); payFeeDetailRefreshFeeMonthDto.setCommunityId(feePos.get(0).getCommunityId()); payFeeDetailRefreshFeeMonthDto.setFeeIds(feeIds); payFeeMonthInnerServiceSMOImpl.doGeneratorFeeMonths(payFeeDetailRefreshFeeMonthDto); payFeeMonthInnerServiceSMOImpl.doGeneratorOweFees(payFeeDetailRefreshFeeMonthDto); return flag; } /** * 计算目标结束时间 * * @param tmpPayFeeRulePo * @param feeConfigDto * @return */ private Date computeTargetEndTime(PayFeeRulePo tmpPayFeeRulePo, FeeConfigDto feeConfigDto) { Date targetEndDate = null; //todo 判断当前费用是否已结束 if (FeeDto.STATE_FINISH.equals(tmpPayFeeRulePo.getState())) { targetEndDate = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getEndTime()); return targetEndDate; } Calendar preEndTimeCal = Calendar.getInstance(); preEndTimeCal.setTime(DateUtil.getDateFromStringB(tmpPayFeeRulePo.getEndTime())); if (StringUtil.isNumber(feeConfigDto.getPrepaymentPeriod())) { preEndTimeCal.add(Calendar.DAY_OF_MONTH, Integer.parseInt(feeConfigDto.getPrepaymentPeriod()) * -1); } Date preEndTime = preEndTimeCal.getTime(); Date maxEndTime = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getMaxTime()); Date billEndTime = DateUtil.getCurrentDate(); //建账时间 Date startDate = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getStartTime()); //计费起始时间 Date endDate = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getEndTime()); //缴费周期 long paymentCycle = Long.parseLong(feeConfigDto.getPaymentCycle()); // 当前时间 - 开始时间 = 月份 double mulMonth = 0.0; mulMonth = DateUtil.dayCompare(startDate, billEndTime); // 月份/ 周期 = 轮数(向上取整) double round = 0.0; if ("1200".equals(feeConfigDto.getPaymentCd())) { // 1200预付费 round = Math.floor(mulMonth / paymentCycle) + 1; } else { //2100后付费 round = Math.floor(mulMonth / paymentCycle); } // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间 targetEndDate = DateUtil.getTargetEndTime(round * paymentCycle, startDate);//目标结束时间 //todo 如果 到了 预付期 产生下个周期的费用 if (DateUtil.getFormatTimeStringB(targetEndDate).equals(DateUtil.getFormatTimeStringB(endDate)) && DateUtil.getCurrentDate().getTime() > preEndTime.getTime() ) { targetEndDate = DateUtil.getTargetEndTime((round + 1) * paymentCycle, startDate);//目标结束时间 } //todo 费用项的结束时间<缴费的结束时间 费用快结束了 取费用项的结束时间 if (maxEndTime.getTime() < targetEndDate.getTime()) { targetEndDate = maxEndTime; } if (DateUtil.getDateFromStringB(tmpPayFeeRulePo.getEndTime()).getTime() > targetEndDate.getTime()) { targetEndDate = DateUtil.getDateFromStringB(tmpPayFeeRulePo.getEndTime()); } return targetEndDate; } }