package common.service.impl; import com.amazonaws.services.dynamodbv2.xspec.S; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import common.model.*; import common.repository.*; import common.service.ShareIncomeService; import dic.ContractStatusEnum; import dic.RoleEnum; import net.sf.json.JSONArray; import offline.model.AccountVO; import offline.model.TrackFlowVO; import offline.repository.TkioOfflineRepository; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Months; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import tkio.model.Account; import tkio.repository.AccountRepository; import tkio.repository.AppRepository; import tkio.service.AccountFlowRestrictService; import util.Constant; import util.ContractBranchUtil; import util.DateUtil; import util.StringUtil; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @Service public class ShareIncomeServiceImpl implements ShareIncomeService { private final Logger logger = LoggerFactory.getLogger(ShareIncomeServiceImpl.class); @Autowired private ContractRepository contractRepository; @Autowired private AuthRepository authRepository; @Autowired private ContractBodyRepository contractBodyRepository; @Autowired private ContractChangeRepository contractChangeRepository; @Autowired private BarrioCityRepository barrioCityRepository; @Autowired private AppRepository appRepository; @Autowired private AccountRepository accountRepository; @Autowired private AccountFlowRestrictService accountFlowRestrictService; @Autowired private PackageBaseRepository packageBaseRepository; @Autowired private TkioFlowRepository tkioFlowRepository; @Autowired private TkioOfflineRepository tkioOfflineRepository; @Override public List<Contract> shareIncomeList(User loginAccount, String startDate, String endDate, String platform, String bodyCode, String serchName) { List<Contract> contracts = new ArrayList<>(); if ("all".equals(bodyCode)) { bodyCode = null; } List<String> financeBodies = null; if (RoleEnum.FINANCE.getKey().equals(loginAccount.getRole())) { Auth auth = authRepository.findByUser(loginAccount.getId()); financeBodies = JSONArray.fromObject(auth.getAuthExtend()); } if (!StringUtils.isEmpty(bodyCode) && !StringUtils.isEmpty(serchName)) { if (financeBodies != null && !financeBodies.contains(bodyCode)) { //沒有权限查看 return contracts; } else { contracts = contractRepository.findShareContranctByDate1(startDate, endDate, platform, bodyCode, serchName); } } else if (!StringUtils.isEmpty(bodyCode)) { if (financeBodies != null && !financeBodies.contains(bodyCode)) { //沒有权限查看 return contracts; } else { contracts = contractRepository.findShareContranctByDate2(startDate, endDate, platform, bodyCode); } } else if (!StringUtils.isEmpty(serchName)) { if (financeBodies != null) { contracts = contractRepository.findShareContranctByDateSercheFinace(startDate, endDate, platform, serchName, financeBodies); } else { contracts = contractRepository.findShareContranctByDateSerche(startDate, endDate, platform, serchName); } } else { if (financeBodies != null) { contracts = contractRepository.findShareContranctByDateFinace(startDate, endDate, platform, financeBodies); } else { contracts = contractRepository.findShareContranctByDate3(startDate, endDate, platform); } } /*contracts = new ArrayList<>(); contracts.add(contractRepository.findOne(4603L));*/ List<ContractBody> bodies = contractBodyRepository.findAll(); Map<String, String> bodiesNameMap = bodies.stream().collect( Collectors.toMap(ContractBody::getCode, ContractBody::getName, (v1, v2) -> v1)); List<BarrioCity> barrioCities = barrioCityRepository.findAll(); Map<Long, BarrioCity> barrioCitiesNameMap = barrioCities.stream().collect(Collectors.toMap(BarrioCity::getId, Function.identity(), (v1, v2) -> v1)); List<PackageBase> packageBases = packageBaseRepository.findByPlatAndStatus(platform, 1); Map<Long, PackageBase> packageBaseMap = packageBases.stream().collect(Collectors.toMap(PackageBase::getId, Function.identity(), (v1, v2) -> v1)); DateTime start = new DateTime(startDate); DateTime end = new DateTime(endDate); long start_ = System.currentTimeMillis(); // for (Contract contract : contracts) { // this.shareIncome4Contract(contract, start, end); // contract.setMyBodyName(bodiesNameMap.get(contract.getMyBodyCode())); // } try (Stream<Contract> streamContract = contracts.parallelStream()) { streamContract.forEachOrdered(v -> { v.setMyBodyName(bodiesNameMap.get(v.getMyBodyCode())); if (v.getBarrioId() != null) v.setBarrioName(barrioCitiesNameMap.get(barrioCitiesNameMap.get(v.getBarrioId()).getParentId()).getName()); if (v.getPriceLevel() != null) v.setPriceLevelName(packageBaseMap.get(v.getPriceLevel()).getPackageName()); }); } if ("tkio".equals(platform)) { this.shareIncome4ContractTKIO_2(contracts, start, end); } else { try (Stream<Contract> streamContract = contracts.parallelStream()) { streamContract.forEachOrdered(v -> { switch (ContractBranchUtil.getValue(platform)) { case "type_one": this.shareIncome4Contract(v, start, end); break; case "type_two": if (v.getPriceLevel() == Constant.tkioPriceLevelNotLimit) { //TKIO不限量套餐 this.shareIncome4Contract(v, start, end); } else { //TKIO普通流量套餐 //this.shareIncome4ContractTwo(v, start, end); this.shareIncome4ContractTKIO(v, start, end, false); } break; case "type_three": this.shareIncome4ContractCAS(v, start, end); break; default: this.shareIncome4Contract(v, start, end); break; } }); } } if (ContractBranchUtil.getValue(platform).equals("type_three")) { List<Contract> removeContracts = new ArrayList<>(); for (Contract contract : contracts) { if (contract.getIntervalUseDays() < 0) { removeContracts.add(contract); } } if (!CollectionUtils.isEmpty(removeContracts)) { contracts.removeAll(removeContracts); } } logger.info("计算分摊收入耗时:{}", (System.currentTimeMillis() - start_)); //结果集result二次加工 if ("tkio".equals(platform)) { //查询主账号为空的 并且 结束日期在查询范围内的 List<Long> allEmailIsNullIds = contractRepository.findAllEmailIsNull(startDate, endDate); for (Contract contract : contracts) { if (StringUtil.isEmpty(contract.getEmail()) || "null".equals(contract.getEmail())) { //不在查询范围内的数据,全部置空 if (allEmailIsNullIds == null || !allEmailIsNullIds.contains(BigInteger.valueOf(contract.getId()))) { contract.setClickFlow(0D); //区间点击数(万次) contract.setIntervaIncomeShare(0L);//区间分摊收入 contract.setAdjustmentFund(0L);//区间调整金额 contract.setIncomeShareAll(0L);//区间总收入 contract.setIncomeGross(0L);//累计总收入(元) } } } } return contracts; } private void shareIncome4ContractCAS(Contract contract, DateTime start, DateTime end) { DateTime[] selected = new DateTime[]{ start, end};//用户筛选开始/结束日期 DateTime[] contractPart = new DateTime[]{ new DateTime(contract.getStartDate()), new DateTime(contract.getEndDate())};//合同开始结束 时间 DateTime[] contractValidPart = new DateTime[]{ new DateTime(contract.getValidStartDate()), new DateTime(contract.getValidEndDate())};//合同有效日 开始结束 时间 DateTime[] usePart = new DateTime[]{ selected[0].compareTo(contractValidPart[0]) <= 0 ? contractValidPart[0] : selected[0], selected[1].compareTo(contractValidPart[1]) >= 0 ? contractValidPart[1] : selected[1] }; usePart[0] = usePart[0].compareTo(usePart[1]) >= 0 ? usePart[1] : usePart[0]; contract.setIntervalUseDays(getDayRange(contractValidPart[0], usePart[1]) + 1); BigDecimal bigDecimal = new BigDecimal(contract.getMoney() / 1.13) .setScale(8, BigDecimal.ROUND_HALF_UP); Long excludTax = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue();//不含税收入*100 contract.setIncomeExcludingTax(excludTax); BigDecimal oneTimeRecognizedRevenue = null; BigDecimal dailyRevenueRecognition = null; if (contract.getOneTime() != null && contract.getOneTime() == false) {//处理cas是否计算一次性收入标识 oneTimeRecognizedRevenue = new BigDecimal("0"); dailyRevenueRecognition = bigDecimal.multiply(new BigDecimal("100")); } else { oneTimeRecognizedRevenue = bigDecimal.multiply(new BigDecimal("0.9")); dailyRevenueRecognition = bigDecimal.multiply(new BigDecimal("10"));//0.1*100=10,前端拿到区间分摊收入/100得到最终的值 } contract.setOneTimeRecognizedRevenue(oneTimeRecognizedRevenue.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); int contractAllDay = getDayRange(contractValidPart[0], contractValidPart[1]) + 1;//合同总天数 //处理精度 BigDecimal dayShareIncome = dailyRevenueRecognition.divide(new BigDecimal(String.valueOf(contractAllDay)), 8, BigDecimal.ROUND_HALF_UP); //作废合同处理 Contract cancleContract = this.cancledShareCAS(contract, oneTimeRecognizedRevenue, contractAllDay, dayShareIncome, contractPart, usePart, selected, contractValidPart); if (cancleContract != null) { return; } //中止合同处理 Contract suspendContract = this.suspendShareCAS(contract, oneTimeRecognizedRevenue, contractAllDay, dayShareIncome, contractPart, usePart, selected, contractValidPart); if (suspendContract != null) { return; } //晚录合同处理 DateTime create = new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")); //录入时间点 DateTime[] creatPoints = new DateTime[]{ create, //录入日 create.dayOfMonth().withMinimumValue() //录入月1日 }; this.afterContractCAS(contract, oneTimeRecognizedRevenue, contractAllDay, dayShareIncome, contractPart, usePart, selected, creatPoints, contractValidPart); } private void afterContractCAS(Contract contract, BigDecimal oneTimeRecognizedRevenue, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] creatPoints, DateTime[] contractValidPart) { int betweenMonth = Months.monthsBetween(contractPart[0], creatPoints[0]).getMonths(); //时间范围内用于计算分摊金额的天数 int daysIncom = getDayRange(usePart[0], usePart[1]) + 1; //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); /*if(checkTwoTime(contractValidPart[0],usePart[1]) && checkTwoTime(usePart[0],contractValidPart[0])){ contract.setIntervaIncomeShare(contract.getIntervaIncomeShare()+oneTimeRecognizedRevenue.setScale(0,BigDecimal.ROUND_HALF_UP).longValue()); }*/ if (checkTwoTime(contractValidPart[0], usePart[1]) && checkTwoTime(usePart[0], contractValidPart[0])) { //contract.setIntervaIncomeShare(contract.getIntervaIncomeShare()+oneTimeRecognizedRevenue.setScale(0,BigDecimal.ROUND_HALF_UP).longValue()); } else { contract.setOneTimeRecognizedRevenue(0.0); } Long adjustmentFund = 0L;//调整金 boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) { isLateContract = true; }/* else if (checkLateContract(contractValidPart[0], creatPoints[0])) { isLateContract = true; }*/ if (isLateContract) { contract.setStatus(ContractStatusEnum.LATE.getKey()); } boolean isLater = true; if (!isLateContract || betweenMonth < 1) { //非合同晚录 contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setOneTimeRecognizedRevenue(0.0); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; daysIncom = getDayRange(useStart, usePart[1]) + 1; contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); /*if(checkTwoTime(contractValidPart[0],usePart[1]) && checkTwoTime(useStart,contractValidPart[0])){ contract.setIntervaIncomeShare(contract.getIntervaIncomeShare()+oneTimeRecognizedRevenue.setScale(0,BigDecimal.ROUND_HALF_UP).longValue()); }*/ adjustmentFund = shareMultiply(dayShareIncome, new BigDecimal(getDayRange(contractValidPart[0], creatPoints[1].plusDays(-1)) + 1), 0); adjustmentFund += oneTimeRecognizedRevenue.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 contract.setAdjustmentFund(adjustmentFund); } else { contract.setAdjustmentFund(0L); } } if (checkTwoTime(selected[0], contractValidPart[1]) && checkTwoTime(contractValidPart[1], selected[1])) { contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractValidPart[0], contractValidPart[1]) + 1), dayShareIncome, 0)); contract.setIncomeGross(contract.getIncomeGross() + oneTimeRecognizedRevenue.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } else { contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractValidPart[0], selected[1]) + 1), dayShareIncome, 0)); if (checkTwoTime(contractValidPart[0], selected[1])) { contract.setIncomeGross(contract.getIncomeGross() + oneTimeRecognizedRevenue.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } if (checkTwoTime(contractValidPart[1], selected[1])) { //最后一日分摊金计算处理 Long lastDay; if (isLater) { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome, new BigDecimal(getDayRange(creatPoints[1], contractValidPart[1])), 0); } else { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome, new BigDecimal(getDayRange(contractValidPart[0], contractValidPart[1])), 0); } //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - dayShareIncome.setScale(0, BigDecimal.ROUND_HALF_UP).longValue() + lastDay); } Double v = contract.getOneTimeRecognizedRevenue() * 100L; contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund() + v.longValue()); } private Contract suspendShareCAS(Contract contract, BigDecimal oneTimeRecognizedRevenue, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] contractValidPart) { if (!ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.SUSPEND.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); return contract; } // 合同终止日 或 作废日 DateTime cancelDate = new DateTime(contractChange.getDs()); //中止操作入库时间 DateTime suspendDate = new DateTime(new DateTime(contractChange.getCreateTime()).toString("yyyy-MM-dd")); Long adjustmentFund = 0L; if (checkTwoTime(suspendDate, cancelDate)) { adjustmentFund = 0L; } else { adjustmentFund = shareMultiply(new BigDecimal((getDayRange(cancelDate, suspendDate) + 1) * -1), dayShareIncome, 0); if (checkTwoTime(contractValidPart[0], suspendDate) && checkTwoTime(cancelDate, contractValidPart[0])) { adjustmentFund += oneTimeRecognizedRevenue.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); } else { contract.setOneTimeRecognizedRevenue(0.0); } } DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; int daysIncom = Days.daysBetween(usePart[0], usedEnd).getDays() + 1; daysIncom = daysIncom < 0 ? 0 : daysIncom; //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); /*if(checkTwoTime(contractValidPart[0],usedEnd) && checkTwoTime(usePart[0],contractValidPart[0])){ contract.setIntervaIncomeShare(contract.getIntervaIncomeShare()+oneTimeRecognizedRevenue.setScale(BigDecimal.ROUND_HALF_UP).longValue()); }*/ if (checkTwoTime(contractValidPart[0], usedEnd) && checkTwoTime(usePart[0], contractValidPart[0])) { } else { contract.setOneTimeRecognizedRevenue(0.0); } if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { contract.setAdjustmentFund(adjustmentFund); contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractValidPart[0], cancelDate) + 1), dayShareIncome, 0)); if (checkTwoTime(contractValidPart[0], cancelDate) && checkTwoTime(contractPart[0], contractValidPart[0])) { contract.setIncomeGross(contract.getIntervaIncomeShare() + oneTimeRecognizedRevenue.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } else { contract.setAdjustmentFund(0L); contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractValidPart[0], selected[1]) + 1), dayShareIncome, 0)); if (checkTwoTime(contractValidPart[0], cancelDate) && checkTwoTime(contractPart[0], contractValidPart[0])) { contract.setIncomeGross(contract.getIntervaIncomeShare() + oneTimeRecognizedRevenue.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } Double v = contract.getOneTimeRecognizedRevenue() * 100L; contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund() + v.longValue()); return contract; } private Contract cancledShareCAS(Contract contract, BigDecimal oneTimeRecognizedRevenue, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] contractValidPart) { if (!ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); return contract; } // 合同终止日 或 作废日 DateTime cancelDate = new DateTime(contractChange.getDs()); Long adjustmentFund = shareMultiply(new BigDecimal((getDayRange(contractValidPart[0], cancelDate) + 1) * -1), dayShareIncome, 0); adjustmentFund -= oneTimeRecognizedRevenue.multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); if (checkTwoTime(contractValidPart[0], selected[1]) && checkTwoTime(selected[0], contractValidPart[0])) { } else { contract.setOneTimeRecognizedRevenue(0.0); } DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; int daysIncom = Days.daysBetween(usePart[0], usedEnd).getDays() + 1; daysIncom = daysIncom < 0 ? 0 : daysIncom; contract.setIntervalUseDays(getDayRange(contractValidPart[0], usedEnd) + 1); //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { contract.setAdjustmentFund(adjustmentFund); } else { contract.setAdjustmentFund(0L); } contract.setIncomeGross(0L); Double v = contract.getOneTimeRecognizedRevenue() * 100L; contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund() + v.longValue()); return contract; } /** * 功能描述:增加补充协议的逻辑 * * @author liyin * @date 2020/11/5 */ private void shareIncome4ContractTKIO_2(List<Contract> contracts, DateTime start, DateTime end) { Multimap<String, Contract> multimap = ArrayListMultimap.create(); //查出所有报表->进行代码分组,按照email分组 计算 try (Stream<Contract> streamContract = contracts.parallelStream()) { streamContract.forEachOrdered(v -> { if (!StringUtil.isEmpty(v.getEmail())) { multimap.put(v.getEmail(), v); } else { if (v.getPriceLevel() == Constant.tkioPriceLevelNotLimit) { int contractAllDay = getDayRange(new DateTime(v.getStartDate()), new DateTime(v.getEndDate())) + 1;//合同总天数 v.setUnitPrice(new BigDecimal(v.getMoney() / 1.06 / contractAllDay).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); } else { v.setUnitPrice(new BigDecimal(v.getMoney() / 1.06 / v.getTrackFlow()) .setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); } v.setClickFlow(0.0); v.setAdjustmentFund(0L); if (checkTwoTime(new DateTime(v.getEndDate()), end) || checkTwoTime(start, new DateTime(v.getEndDate()))) { v.setIntervaIncomeShare(new BigDecimal(v.getMoney() / 1.06 * 100).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); v.setIncomeGross(v.getIntervaIncomeShare()); v.setIncomeShareAll(v.getIntervaIncomeShare()); } } }); } //遍历map,找出主合同,注:补充协议不能与补充协议互相绑定 Set<String> emails = multimap.keySet(); for (String email : emails) { //开始处理 Collection<Contract> groupContracts = multimap.get(email); HashMap<String, Contract> map = new HashMap<>(); //处理查询区间内只有补充协议没有主合同的情况 for (Contract groupContract : groupContracts) { map.put(groupContract.getContractCode(), groupContract); } for (Contract groupContract : groupContracts) { if ("2".equals(groupContract.getContractType())) { //2021年7月19日21:01:20 补充:可能会出现补充协议套娃(B1,B2两个补充协议,但是其中B1补充协议因为主体权限原因没有查出来,B2要依赖B1计算单价,这时候要查出B1),所以需要重新查询一遍 //不管主账号在不在,按照现有条件无法判断该补充协议是否被其他合同关联 //只判断补充协议是因为,如果只有首签/续签的权限合同,对于后面的补充协议是不影响的 //Contract contract = map.get(groupContract.getRelationCode());//补充协议查找map内是否有他的主合同(首次/续约) //if(contract==null){ List<Contract> contractList = contractRepository.findByCreateTimeAndCodeNotOwn(groupContract.getRelationCode(), DateUtil.format(groupContract.getCreateTime(), DateUtil.C_TIME_PATTON_DEFAULT), groupContract.getId()); for (Contract contract1 : contractList) { if (StringUtils.isEmpty(map.get(contract1.getContractCode()))) { map.put(contract1.getContractCode(), contract1); } } groupContracts = map.values();//只要不加入传进来的那个list里面就不会影响查询的列表 break; } else if ((groupContracts.size() == 1 && !StringUtils.isEmpty(groupContract.getNextSignedDate())) || (!"2".equals(groupContract.getContractType()) && map.get(groupContract.getNextSignedContractCode()) == null)) { List<Contract> contractList = contractRepository.findByRelationCode(groupContract.getContractCode()); for (Contract contract1 : contractList) { if (StringUtils.isEmpty(map.get(contract1.getContractCode()))) { map.put(contract1.getContractCode(), contract1); } } groupContracts = map.values(); break; } } //再次进行合同的关系分组--->master List<ContractVO> contractVOs = new ArrayList<>(); for (Contract contract : groupContracts) { if (!"2".equals(contract.getContractType())) { ContractVO contractVO = new ContractVO(); contractVO.setMaster(contract); contractVOs.add(contractVO); } } //再次进行合同的关系分组--->sideLette for (ContractVO contractVO : contractVOs) { for (Contract contract : groupContracts) { if ("2".equals(contract.getContractType()) && contractVO.getMaster().getContractCode().equals(contract.getRelationCode())) { List<Contract> sideLette = contractVO.getSideLette(); if (sideLette == null) { sideLette = new ArrayList<>(); } sideLette.add(contract); contractVO.setSideLette(sideLette); } } } //1个合同<----->多个合同 //1个合同->走普通的,走tkio逻辑 for (ContractVO contractVO : contractVOs) { if (CollectionUtils.isEmpty(contractVO.getSideLette())) {//1个合同 Contract master = contractVO.getMaster(); if (master.getPriceLevel() == Constant.tkioPriceLevelNotLimit) {//无限流量走adi计算逻辑 shareIncome4Contract(master, start, end); } else {//普通流量走tkio计算逻辑 shareIncome4ContractTKIO(master, start, end, false); } } else {//该首次签约/续约合同 绑定了补充协议合同 List<Contract> sideLette = contractVO.getSideLette(); /*Boolean isNotLimit = false; for (Contract contract : sideLette) { if(contract.getPriceLevel()==Constant.tkioPriceLevelNotLimit){ isNotLimit = true; } }*/ //补充协议按照录入时间排序->从后到前,从大到小反推计算合同 sideLette.add(contractVO.getMaster()); Contract[] contractsArray = orderByCreateTime(sideLette); for (int j = 0; j < contractsArray.length; j++) { //计算除了最后一个的每个合同历史所用流量 boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contractsArray[j].getStatus())) { isLateContract = true; } else if (checkLateContract(new DateTime(contractsArray[j].getSignedDate() == null ? contractsArray[j].getStartDate() : contractsArray[j].getSignedDate()), new DateTime(new DateTime(contractsArray[j].getCreateTime()).toString("yyyy-MM-dd")))) { isLateContract = true; contractsArray[j].setStatus(ContractStatusEnum.LATE.getKey()); } String startDate = null; if (isLateContract && j > 0) {//补充协议晚录 startDate = new DateTime(contractsArray[j].getCreateTime()).dayOfMonth().withMinimumValue().toString("yyyy-MM-dd"); } else { startDate = contractsArray[j].getSignedDate() == null ? contractsArray[j].getStartDate() : contractsArray[j].getSignedDate(); } String endDate = contractsArray[j].getNextSignedDate() == null ? contractsArray[j].getEndDate() : contractsArray[j].getNextSignedDate(); ArrayList<String> codes = new ArrayList<>(); for (int k = 0; k <= j; k++) { codes.add(contractsArray[k].getContractCode()); } BigDecimal flow = tkioFlowRepository.sumFlowByDsAndContractCodes(startDate, endDate, codes); double i1 = flow == null ? 0 : flow.divide(new BigDecimal(10000.0)).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue(); if (j > 0) {//上一份合同超出的流量算在当前合同上(肯定在签订日之前)合同的开始日(补充协议的开始日就是原合同的开始日,结束日为上一个合同的下一个签订日) BigDecimal bigDecimal = tkioFlowRepository.sumFlowByContractCodeAndDs(contractsArray[j].getContractCode(), contractsArray[j].getStartDate(), contractsArray[j - 1].getNextSignedDate()); double i = bigDecimal == null ? 0 : bigDecimal.divide(new BigDecimal(10000.0)).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue(); i1 += i; } contractsArray[j].setHistoryTkioFlow(i1); } //补充协议核心逻辑 //能运行到这里说明只有补充协议才会出现无限流量(最后一个),如果是主合同无限流量,就不可能有补充协议 for (int i = 0; i < contractsArray.length; i++) { if (i > 0) { Contract contract = contractsArray[i]; if (contracts.contains(contract)) { //计算当前单价 double totalFlow = 0; double totalprice = 0.0; double accruingFlow = 0; double accruingAmounts = 0.0; for (int j = 0; j < i; j++) { totalFlow += contractsArray[j].getTrackFlow(); totalprice += new BigDecimal(contractsArray[j].getMoney() / 1.06).setScale(16, BigDecimal.ROUND_HALF_UP).doubleValue(); double currentFlow = totalFlow - accruingFlow; double currentMoney = totalprice - accruingAmounts; contractsArray[j].setUnitPriceAccurate(new BigDecimal(currentMoney / currentFlow) .setScale(16, BigDecimal.ROUND_HALF_UP));//存储16位单价 accruingAmounts += new BigDecimal(currentMoney / currentFlow * contractsArray[j].getHistoryTkioFlow()) .setScale(16, BigDecimal.ROUND_HALF_UP).doubleValue();//当前合同之前的累计消耗金额 accruingFlow += contractsArray[j].getHistoryTkioFlow();//当前合同之前的累计消耗流量,万单位 } totalFlow = totalFlow - accruingFlow < 0 ? 0 : totalFlow - accruingFlow; totalFlow = totalFlow + contract.getTrackFlow(); totalprice = totalprice - accruingAmounts < 0 ? 0 : totalprice - accruingAmounts; totalprice = totalprice + new BigDecimal(contract.getMoney() / 1.06).setScale(16, BigDecimal.ROUND_HALF_UP).doubleValue(); contract.setIncomeExcludingTax(new BigDecimal(totalprice) .setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue()); BigDecimal unitPriceAccurate = null; if (!contract.getPriceLevel().equals(Constant.tkioPriceLevelNotLimit)) { unitPriceAccurate = new BigDecimal(totalprice / totalFlow) .setScale(16, BigDecimal.ROUND_HALF_UP);//当前合同的单价 //四舍五入单价 double unitPrice = unitPriceAccurate.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); contract.setUnitPrice(unitPrice); } boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) { isLateContract = true; } else if (checkLateContract(new DateTime(contract.getSignedDate() == null ? contract.getStartDate() : contract.getSignedDate()), new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")))) { isLateContract = true; contract.setStatus(ContractStatusEnum.LATE.getKey()); } //正常查流量 DateTime[] selected = {start, end};//用户筛选日期区间 DateTime[] contractPart = new DateTime[]{ new DateTime(contract.getSignedDate()), new DateTime(contract.getNextSignedDate() == null ? contract.getEndDate() : contract.getNextSignedDate())};//合同开始结束(下一份合同签订日前一天) 时间 DateTime[] usePart = new DateTime[]{ selected[0].compareTo(contractPart[0]) <= 0 ? contractPart[0] : selected[0], selected[1].compareTo(contractPart[1]) >= 0 ? contractPart[1] : selected[1] }; usePart[0] = usePart[0].compareTo(usePart[1]) >= 0 ? usePart[1] : usePart[0]; DateTime create = new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")); //录入时间点 DateTime[] creatPoints = new DateTime[]{ create, //录入日 create.dayOfMonth().withMinimumValue() //录入月1日 }; if (selected[1].isBefore(contractPart[0])) { contract.setUnitPrice(0.0); contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setClickFlow(0.0); contract.setIncomeGross(0L); contracts.remove(contract);//移出列表 } else if (!contract.getPriceLevel().equals(Constant.tkioPriceLevelNotLimit)) { boolean isLater = true; if (!isLateContract) {//正常合同 //补充协议的开始时间和结束时间是与主合同时间一致的,所以需要按照补充协议的字段再次判断补充协议是否在区间选择内 if (selected[0].compareTo(contractPart[1]) > 0 || selected[1].compareTo(contractPart[0]) < 0) { contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setClickFlow(0.0); contract.setIncomeGross(0L); } else { ArrayList<String> codes = new ArrayList<>(); for (int k = 0; k <= i; k++) { codes.add(contractsArray[k].getContractCode()); } contract.setClickFlow(0.0); BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); //调整金,正常情况下可能存在之前合同超出的流量所产生的调整金(记录在签订日) BigDecimal beforSigndFlow = null; if (checkTwoTime(selected[0], contractPart[0]) && checkTwoTime(contractPart[1], selected[0])) { DateTime startDate = new DateTime(contract.getStartDate()); DateTime endDate = contractPart[0].plusDays(-1);//签约日前一天 beforSigndFlow = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), startDate.toString("yyyy-MM-dd"), endDate.toString("yyyy-MM-dd")); beforSigndFlow = beforSigndFlow == null ? new BigDecimal(0) : beforSigndFlow; BigDecimal beforSigndAdjustmentFund = beforSigndFlow.divide(new BigDecimal(10000.0 / 100)).multiply(unitPriceAccurate); contract.setAdjustmentFund(beforSigndAdjustmentFund.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } else { contract.setAdjustmentFund(0L); } contract.setIncomeShareAll(contract.getIntervaIncomeShare()); //todo 累计总收入,还得算上签订日之前的流量 clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes); clickFlow = clickNum == null ? 0L : clickNum.longValue(); if (beforSigndFlow != null) { clickFlow += beforSigndFlow.intValue(); } contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 所有调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setClickFlow(0.0); contract.setIncomeGross(0L); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; ArrayList<String> codes = new ArrayList<>(); for (int k = 0; k <= i; k++) { codes.add(contractsArray[k].getContractCode()); } BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(useStart.toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } BigDecimal beforSigndFlow = null; //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 //合同开始日期,合同录入日期的一号,-1就是上个月最后一天 //contractPart[0], creatPoints[1].plusDays(-1) //晚录调整金 clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[0].toString("yyyy-MM-dd"), creatPoints[1].plusDays(-1).toString("yyyy-MM-dd"), codes); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } contract.setAdjustmentFund(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); //超出流量调整金 if (checkTwoTime(selected[0], contractPart[0]) && checkTwoTime(contractPart[1], selected[0])) { DateTime startDate = new DateTime(contract.getStartDate()); DateTime endDate = creatPoints[1].plusDays(-1);//签约录入日前一天 beforSigndFlow = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), startDate.toString("yyyy-MM-dd"), endDate.toString("yyyy-MM-dd")); beforSigndFlow = beforSigndFlow == null ? new BigDecimal(0) : beforSigndFlow; BigDecimal beforSigndAdjustmentFund = beforSigndFlow.divide(new BigDecimal(10000.0 / 100)).multiply(unitPriceAccurate); contract.setAdjustmentFund(contract.getAdjustmentFund() + beforSigndAdjustmentFund.setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } //处理上一个合同的调整金 if (i > 0) { contractsArray[i - 1].setAdjustmentFund(contractsArray[i - 1].getAdjustmentFund() - contractsArray[i - 1].getUnitPriceAccurate().multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } else { contract.setAdjustmentFund(0L); } //累计总收入 clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes); clickFlow = clickNum == null ? 0L : clickNum.longValue(); if (beforSigndFlow != null) { clickFlow += beforSigndFlow.intValue(); } contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } //判断合同真实结束日期之前判断该合同有没有下一份合同 if (contract.getNextSignedContractCode() == null && checkTwoTime(contractPart[1], selected[1])) { //最后一日分摊收入计算处理(合同的最后一天,不管流量剩余多少,都算作做最后一天的收入) Long lastDay; DateTime lastDate[]; if (isLater) { lastDate = new DateTime[]{creatPoints[1], contractPart[1].plusDays(-1)}; } else { lastDate = new DateTime[]{contractPart[0], contractPart[1].plusDays(-1)}; } //合同除去最后一天的流量 ArrayList<String> codes = new ArrayList<>(); for (int k = 0; k <= i; k++) { codes.add(contractsArray[k].getContractCode()); } BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(lastDate[0].toString("yyyy-MM-dd"), lastDate[1].toString("yyyy-MM-dd"), codes); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } long beforeTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //最后一天的流量 clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[1].toString("yyyy-MM-dd"), contractPart[1].toString("yyyy-MM-dd"), codes); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); long lastDayTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //合同的税后总金额减去最后合同一日之前的钱和调整金 long excludTax = new BigDecimal(totalprice) .setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue(); //TODO 超出的流量算在了调整金了这里好像减去了 lastDay = excludTax - contract.getAdjustmentFund() - beforeTheMoney; //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - lastDayTheMoney + lastDay); contract.setIncomeGross(contract.getIncomeGross() - lastDayTheMoney + lastDay); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); } else {//不限量套餐 int contractAllDay = getDayRange(contractPart[0], contractPart[1]) + 1;//合同总天数 BigDecimal dayShareIncome = new BigDecimal(totalprice / contractAllDay) .setScale(16, BigDecimal.ROUND_HALF_UP); contract.setUnitPrice(dayShareIncome.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());//设置不限量套餐的单价 int betweenMonth = Months.monthsBetween(contractPart[0], creatPoints[0]).getMonths(); //时间范围内用于计算分摊金额的天数 int daysIncom = getDayRange(usePart[0], usePart[1]) + 1; //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(daysIncom), 0)); //无限流量套餐合同的区间点击数 ArrayList<String> codes = new ArrayList<>(); for (int k = 0; k <= i; k++) { codes.add(contractsArray[k].getContractCode()); } BigDecimal clickNumLimit = tkioFlowRepository.sumFlowByDsAndContractCodes(usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes); long clickFlowLimit = clickNumLimit == null ? 0L : clickNumLimit.longValue(); if (clickFlowLimit != 0) { contract.setClickFlow(new BigDecimal(clickFlowLimit / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } else { contract.setClickFlow(0.0); } Long adjustmentFund = 0L;//调整金 if (isLateContract) { contract.setStatus(ContractStatusEnum.LATE.getKey()); } boolean isLater = true; if (!isLateContract || betweenMonth < 1) { //非合同晚录 contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; daysIncom = getDayRange(useStart, usePart[1]) + 1; contract.setIntervaIncomeShare(shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(daysIncom), 0)); adjustmentFund = shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(getDayRange(contractPart[0], creatPoints[1].plusDays(-1)) + 1), 0); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 contract.setAdjustmentFund(adjustmentFund); } else { contract.setAdjustmentFund(0L); } //处理上一份合同 BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[0].toString("yyyy-MM-dd"), creatPoints[1].plusDays(-1).toString("yyyy-MM-dd"), codes); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } if (i > 0) { contractsArray[i - 1].setAdjustmentFund(contractsArray[i - 1].getAdjustmentFund() - contractsArray[i - 1].getUnitPriceAccurate().multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(getDayRange(contractPart[0], contractPart[1]) + 1), 0)); } else { contract.setIncomeGross(shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(getDayRange(contractPart[0], selected[1]) + 1), 0)); } if (checkTwoTime(contractPart[1], selected[1])) { //最后一日分摊金计算处理 Long lastDay; if (isLater) { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(getDayRange(creatPoints[1], contractPart[1])), 0); } else { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome.multiply(new BigDecimal(100L)), new BigDecimal(getDayRange(contractPart[0], contractPart[1])), 0); } //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - dayShareIncome.multiply(new BigDecimal(100L)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue() + lastDay); contract.setIncomeGross(contract.getIncomeGross() - dayShareIncome.multiply(new BigDecimal(100L)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue() + lastDay); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); } } } else { Contract contractMaster = contractsArray[i]; if (contracts.contains(contractMaster)) { String endDate = contractMaster.getEndDate(); contractMaster.setEndDate(contractMaster.getNextSignedDate()); shareIncome4ContractTKIO(contractMaster, start, end, true);//到结束的前一天 contractMaster.setEndDate(endDate); } } } } } } } public Contract[] orderByCreateTime(List<Contract> contracts) {//从小到大排序 Contract[] contractsArray = new Contract[contracts.size()]; contractsArray = contracts.toArray(contractsArray); for (int i = 0; i < contractsArray.length - 1; i++) { for (int j = 0; j < contractsArray.length - 1 - i; j++) { if (contractsArray[j].getCreateTime().getTime() > contractsArray[j + 1].getCreateTime().getTime()) { Contract temp = contractsArray[j]; contractsArray[j] = contractsArray[j + 1]; contractsArray[j + 1] = temp; } else if (contractsArray[j].getCreateTime().getTime() == contractsArray[j + 1].getCreateTime().getTime()) { String contractCode = StringUtil.matchNumber(contractsArray[j].getContractCode()); String contractCodeMin = StringUtil.matchNumber(contractsArray[j + 1].getContractCode()); if (Long.valueOf(contractCode) > Long.valueOf(contractCodeMin)) { Contract temp = contractsArray[j]; contractsArray[j] = contractsArray[j + 1]; contractsArray[j + 1] = temp; } } } } return contractsArray; } private void shareIncome4ContractTKIO(Contract contract, DateTime start, DateTime end, Boolean isMore) { DateTime[] selected = new DateTime[]{ start, end};//用户筛选开始/结束日期 DateTime[] contractPart = new DateTime[]{ new DateTime(contract.getStartDate()), new DateTime(contract.getEndDate())};//合同开始结束 时间 DateTime[] usePart = new DateTime[]{ selected[0].compareTo(contractPart[0]) <= 0 ? contractPart[0] : selected[0], selected[1].compareTo(contractPart[1]) >= 0 ? contractPart[1] : selected[1] }; usePart[0] = usePart[0].compareTo(usePart[1]) >= 0 ? usePart[1] : usePart[0]; Long excludTax = new BigDecimal(contract.getMoney() / 1.06) .setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue();//不含税收入*100 contract.setIncomeExcludingTax(excludTax); BigDecimal unitPriceAccurate = null; //计算单价,精准保留16位数 try { unitPriceAccurate = new BigDecimal(contract.getMoney() / 1.06 / contract.getTrackFlow()) .setScale(16, BigDecimal.ROUND_HALF_UP); } catch (Exception e) { e.printStackTrace(); } //四舍五入单价 double unitPrice = unitPriceAccurate.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); //不限量套餐会在方法里面重新赋值单价 contract.setUnitPrice(unitPrice); //作废合同 累计收入= 0 //中止合同 累计收入= 如果中止日期在选择日期之内,【合同开始日期-中止日期】,否则【合同开始日期-选择结束日期】,不需要考虑调整金 //晚录合同 累计收入= 同下 //正常合同 累计收入= 如果合同结束日期在选择日期之内,则直接取 [合同金额/1.06]得到总金额 ,否则 【合同开始日期-选择结束日期】 //作废合同处理 Contract cancleContract = this.cancledShareFlow(contract, unitPriceAccurate, usePart, selected); if (cancleContract != null) { return; } //中止合同处理 Contract suspendContract = this.suspendShareFlow(contract, unitPriceAccurate, contractPart, usePart, selected); if (suspendContract != null) { return; } //补充协议的主合同特殊处理 if (isMore && new DateTime(contract.getNextSignedDate()).isBefore(selected[0])) { contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setClickFlow(0.0); contract.setIncomeGross(0L); return; } //晚录合同处理//正常合同处理 DateTime create = new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")); //录入时间点 DateTime[] creatPoints = new DateTime[]{ create, //录入日 create.dayOfMonth().withMinimumValue() //录入月1日 }; this.afterContractFlow(contract, unitPriceAccurate, contractPart, usePart, selected, creatPoints, isMore); } private void afterContractFlow(Contract contract, BigDecimal unitPriceAccurate, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] creatPoints, Boolean isMore) { Long adjustmentFund = 0L;//调整金 contract.setClickFlow(0.0); boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) { isLateContract = true; }/* else if (checkLateContract(contractPart[0], creatPoints[0])) { isLateContract = true; contract.setStatus(ContractStatusEnum.LATE.getKey()); }*/ boolean isLater = true; if (!isLateContract) { //非合同晚录 BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); if (!isMore && checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contractPart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); contract.setIncomeGross(0L); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), useStart.toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 BigDecimal clickNumReal = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), selected[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd")); int clickNumRealFlow = clickNumReal == null ? 0 : clickNumReal.intValue(); contract.setClickFlow(new BigDecimal(clickNumRealFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 //合同开始日期,合同录入日期的一号,-1就是上个月最后一天 //contractPart[0], creatPoints[1].plusDays(-1) clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contractPart[0].toString("yyyy-MM-dd"), creatPoints[1].plusDays(-1).toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 } contract.setAdjustmentFund(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } else { contract.setAdjustmentFund(0L); } if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contractPart[0].toString("yyyy-MM-dd"), selected[1].plusDays(-1).toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } if (!isMore && checkTwoTime(contractPart[1], selected[1])) { //最后一日分摊收入计算处理(合同的最后一天,不管流量剩余多少,都算作做最后一天的收入) Long lastDay; DateTime lastDate[]; if (isLater) { lastDate = new DateTime[]{creatPoints[1], contractPart[1].plusDays(-1)}; } else { lastDate = new DateTime[]{contractPart[0], contractPart[1].plusDays(-1)}; } //合同除去最后一天的流量 BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), lastDate[0].toString("yyyy-MM-dd"), lastDate[1].toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } long beforeTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //最后一天的流量 clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contractPart[1].toString("yyyy-MM-dd"), contractPart[1].toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); long lastDayTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //合同的税后总金额减去最后合同一日之前的钱和调整金 lastDay = contract.getIncomeExcludingTax() - contract.getAdjustmentFund() - beforeTheMoney; //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - lastDayTheMoney + lastDay); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); } private Contract suspendShareFlow(Contract contract, BigDecimal unitPriceAccurate, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.SUSPEND.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); contract.setClickFlow(0.0); return contract; } // 合同中止日 DateTime cancelDate = new DateTime(contractChange.getDs()); //中止操作入库时间 DateTime suspendDate = new DateTime(new DateTime(contractChange.getCreateTime()).toString("yyyy-MM-dd")); contract.setClickFlow(0.0); //调整金 Long adjustmentFund = 0L; if (checkTwoTime(suspendDate, cancelDate)) { adjustmentFund = 0L; } else { //查询调整金的点击,日期开始结束时间注意不能颠倒 BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), cancelDate.toString("yyyy-MM-dd"), suspendDate.toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } adjustmentFund = unitPriceAccurate.multiply(clickTenThousand.multiply(new BigDecimal(-1))).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); } //调整金 contract.setAdjustmentFund(adjustmentFund); DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; //查询开始->中止日期的点击(有收入的点击),不包括调整金 BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), usePart[0].toString("yyyy-MM-dd"), usedEnd.toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入,乘以100,前端除以100 long share = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); contract.setIntervaIncomeShare(share); contract.setIncomeShareAll(share + adjustmentFund); if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contractPart[0].toString("yyyy-MM-dd"), selected[1].toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } return contract; } private Contract cancledShareFlow(Contract contract, BigDecimal unitPriceAccurate, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); contract.setClickFlow(0.0); return contract; } DateTime cancelDate = new DateTime(contractChange.getDs());//合同作废日 DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; BigDecimal clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), usePart[0].toString("yyyy-MM-dd"), usedEnd.toString("yyyy-MM-dd")); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); //区间点击数 contract.setClickFlow(0.0); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入,乘以100,前端除以100 long share = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); contract.setIntervaIncomeShare(share); //调整金 if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { clickNum = tkioFlowRepository.sumFlowByContractCodeAndDs(contract.getContractCode(), contract.getStartDate(), usedEnd.toString("yyyy-MM-dd")); clickFlow = clickNum == null ? 0L : clickNum.longValue(); //区间点击数 clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setAdjustmentFund(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue() * -1L); } else { contract.setAdjustmentFund(0L); } } else { contract.setAdjustmentFund(0L); } //分摊总收入 contract.setIncomeShareAll(0L); contract.setIncomeGross(0L); return contract; } //需求禅道 1608 public void shareIncome4ContractTwo(Contract contract, DateTime start, DateTime end) { DateTime[] selected = new DateTime[]{ start, end};//用户筛选开始/结束日期 DateTime[] contractPart = new DateTime[]{ new DateTime(contract.getStartDate()), new DateTime(contract.getEndDate())};//合同开始结束 时间 DateTime[] usePart = new DateTime[]{ selected[0].compareTo(contractPart[0]) <= 0 ? contractPart[0] : selected[0], selected[1].compareTo(contractPart[1]) >= 0 ? contractPart[1] : selected[1] }; usePart[0] = usePart[0].compareTo(usePart[1]) >= 0 ? usePart[1] : usePart[0]; Long excludTax = new BigDecimal(contract.getMoney() / 1.06) .setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue();//不含税收入*100 contract.setIncomeExcludingTax(excludTax); //计算单价,精准保留16位数 BigDecimal unitPriceAccurate = new BigDecimal(contract.getMoney() / 1.06 / contract.getTrackFlow()) .setScale(16, BigDecimal.ROUND_HALF_UP); //四舍五入单价 double unitPrice = unitPriceAccurate.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); //不限量套餐会在方法里面重新赋值单价 contract.setUnitPrice(unitPrice); //查询用户下所有appkey Account account = accountRepository.findByEmail(contract.getEmail()); List<Account> accountList = accountRepository.findByRootParent(account.getRootParent()); List<Long> idList = new ArrayList<>(); for (Account ac : accountList) { idList.add(ac.getId()); } List<String> appkeys = appRepository.findAppkeysNotDebug(idList); String appkeyStr = String.join("','", appkeys); appkeyStr = "'" + appkeyStr + "'"; //作废合同 累计收入= 0 //中止合同 累计收入= 如果中止日期在选择日期之内,【合同开始日期-中止日期】,否则【合同开始日期-选择结束日期】,不需要考虑调整金 //晚录合同 累计收入= 同下 //正常合同 累计收入= 如果合同结束日期在选择日期之内,则直接取 [合同金额/1.06]得到总金额 ,否则 【合同开始日期-选择结束日期】 //作废合同处理 Contract cancleContract = this.cancledShareTKIO(contract, appkeyStr, unitPriceAccurate, usePart, selected); if (cancleContract != null) { return; } //中止合同处理 Contract suspendContract = this.suspendShareTKIO(contract, appkeyStr, unitPriceAccurate, contractPart, usePart, selected); if (suspendContract != null) { return; } //晚录合同处理//正常合同处理 DateTime create = new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")); //录入时间点 DateTime[] creatPoints = new DateTime[]{ create, //录入日 create.dayOfMonth().withMinimumValue() //录入月1日 }; this.afterContractTKIO(contract, appkeyStr, unitPriceAccurate, contractPart, usePart, selected, creatPoints); } private void afterContractTKIO(Contract contract, String appkeyStr, BigDecimal unitPriceAccurate, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] creatPoints) { Long adjustmentFund = 0L;//调整金 contract.setClickFlow(0.0); boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) { isLateContract = true; } else if (checkLateContract(contractPart[0], creatPoints[0])) { isLateContract = true; contract.setStatus(ContractStatusEnum.LATE.getKey()); } boolean isLater = true; if (!isLateContract) { //非合同晚录 BigInteger clickNum = accountFlowRestrictService.getTotalNum(usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = accountFlowRestrictService.getTotalNum(contractPart[0].toString("yyyy-MM-dd"), selected[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setClickFlow(0.0); contract.setIncomeGross(0L); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; BigInteger clickNum = accountFlowRestrictService.getTotalNum(useStart.toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入 contract.setIntervaIncomeShare(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 //合同开始日期,合同录入日期的一号,-1就是上个月最后一天 //contractPart[0], creatPoints[1].plusDays(-1) clickNum = accountFlowRestrictService.getTotalNum(contractPart[0].toString("yyyy-MM-dd"), creatPoints[1].plusDays(-1).toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 } contract.setAdjustmentFund(unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } else { contract.setAdjustmentFund(0L); } if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = accountFlowRestrictService.getTotalNum(contractPart[0].toString("yyyy-MM-dd"), selected[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } } if (checkTwoTime(contractPart[1], selected[1])) { //最后一日分摊收入计算处理(合同的最后一天,不管流量剩余多少,都算作做最后一天的收入) Long lastDay; DateTime lastDate[]; if (isLater) { lastDate = new DateTime[]{creatPoints[1], contractPart[1].plusDays(-1)}; } else { lastDate = new DateTime[]{contractPart[0], contractPart[1].plusDays(-1)}; } //合同除去最后一天的流量 BigInteger clickNum = accountFlowRestrictService.getTotalNum(lastDate[0].toString("yyyy-MM-dd"), lastDate[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } long beforeTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //最后一天的流量 clickNum = accountFlowRestrictService.getTotalNum(contractPart[1].toString("yyyy-MM-dd"), contractPart[1].toString("yyyy-MM-dd"), appkeyStr, "account_track_flow_restrict", "click_sum"); clickFlow = clickNum == null ? 0L : clickNum.longValue(); clickTenThousand = new BigDecimal(0); if (clickFlow != 0) clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); long lastDayTheMoney = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); //合同的税后总金额减去最后合同一日之前的钱和调整金 lastDay = contract.getIncomeExcludingTax() - contract.getAdjustmentFund() - beforeTheMoney; //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - lastDayTheMoney + lastDay); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); } private Contract suspendShareTKIO(Contract contract, String appkeys, BigDecimal unitPriceAccurate, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.SUSPEND.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); contract.setClickFlow(0.0); return contract; } // 合同中止日 DateTime cancelDate = new DateTime(contractChange.getDs()); //中止操作入库时间 DateTime suspendDate = new DateTime(new DateTime(contractChange.getCreateTime()).toString("yyyy-MM-dd")); contract.setClickFlow(0.0); //调整金 Long adjustmentFund = 0L; if (checkTwoTime(suspendDate, cancelDate)) { adjustmentFund = 0L; } else { //查询调整金的点击,日期开始结束时间注意不能颠倒 BigInteger clickNum = accountFlowRestrictService.getTotalNum(cancelDate.toString("yyyy-MM-dd"), suspendDate.toString("yyyy-MM-dd"), appkeys, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); } adjustmentFund = unitPriceAccurate.multiply(clickTenThousand.multiply(new BigDecimal(-1))).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); } //调整金 contract.setAdjustmentFund(adjustmentFund); DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; //查询开始->中止日期的点击(有收入的点击),不包括调整金 BigInteger clickNum = accountFlowRestrictService.getTotalNum(usePart[0].toString("yyyy-MM-dd"), usedEnd.toString("yyyy-MM-dd"), appkeys, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入,乘以100,前端除以100 long share = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); contract.setIntervaIncomeShare(share); contract.setIncomeShareAll(share + adjustmentFund); if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(contract.getIncomeExcludingTax()); } else { //累计总收入 clickNum = accountFlowRestrictService.getTotalNum(contractPart[0].toString("yyyy-MM-dd"), selected[1].toString("yyyy-MM-dd"), appkeys, "account_track_flow_restrict", "click_sum"); clickFlow = clickNum == null ? 0L : clickNum.longValue(); contract.setIncomeGross(unitPriceAccurate.multiply(new BigDecimal(clickFlow / 10000.0 * 100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue()); } return contract; } private Contract cancledShareTKIO(Contract contract, String appkeys, BigDecimal unitPriceAccurate, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); contract.setClickFlow(0.0); return contract; } DateTime cancelDate = new DateTime(contractChange.getDs());//合同作废日 DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; BigInteger clickNum = accountFlowRestrictService.getTotalNum(usePart[0].toString("yyyy-MM-dd"), usedEnd.toString("yyyy-MM-dd"), appkeys, "account_track_flow_restrict", "click_sum"); long clickFlow = clickNum == null ? 0L : clickNum.longValue(); //区间点击数 contract.setClickFlow(0.0); BigDecimal clickTenThousand = new BigDecimal(0); if (clickFlow != 0) { clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100); //区间点击数 contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue()); } //区间分摊收入,乘以100,前端除以100 long share = unitPriceAccurate.multiply(clickTenThousand).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); contract.setIntervaIncomeShare(share); //调整金 if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { contract.setAdjustmentFund(share * -1L); } else { contract.setAdjustmentFund(0L); } //分摊总收入 contract.setIncomeShareAll(0L); contract.setIncomeGross(0L); return contract; } public void shareIncome4Contract(Contract contract, DateTime start, DateTime end) { DateTime[] selected = new DateTime[]{ start, end};//用户筛选开始/结束日期 DateTime[] contractPart = new DateTime[]{ new DateTime(contract.getStartDate()), new DateTime(contract.getEndDate())};//合同开始结束 时间 DateTime[] usePart = new DateTime[]{ selected[0].compareTo(contractPart[0]) <= 0 ? contractPart[0] : selected[0], selected[1].compareTo(contractPart[1]) >= 0 ? contractPart[1] : selected[1] }; usePart[0] = usePart[0].compareTo(usePart[1]) >= 0 ? usePart[1] : usePart[0]; contract.setIntervalUseDays(getDayRange(contractPart[0], usePart[1]) + 1); Long excludTax = new BigDecimal(contract.getMoney() / 1.06) .setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue();//不含税收入*100 contract.setIncomeExcludingTax(excludTax); int contractAllDay = getDayRange(contractPart[0], contractPart[1]) + 1;//合同总天数 //处理精度 BigDecimal dayShareIncome = new BigDecimal(excludTax * 1.0 / contractAllDay); if ("tkio".equals(contract.getPlatform())) {//设置tkio无限流量的日单价 contract.setUnitPrice(dayShareIncome.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); } //作废合同处理 Contract cancleContract = this.cancledShare(contract, contractAllDay, dayShareIncome, contractPart, usePart, selected); if (cancleContract != null) { return; } //中止合同处理 Contract suspendContract = this.suspendShare(contract, contractAllDay, dayShareIncome, contractPart, usePart, selected); if (suspendContract != null) { return; } //特殊合同处理 Contract specilContract = this.specilContract(contract, dayShareIncome, contractPart, usePart, selected); if (specilContract != null) { return; } //晚录合同处理 DateTime create = new DateTime(new DateTime(contract.getCreateTime()).toString("yyyy-MM-dd")); //录入时间点 DateTime[] creatPoints = new DateTime[]{ create, //录入日 create.dayOfMonth().withMinimumValue() //录入月1日 }; this.afterContract(contract, contractAllDay, dayShareIncome, contractPart, usePart, selected, creatPoints); } private Contract specilContract(Contract contract, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected) { if (!"QQ-ADI-20190729-57".equals(contract.getContractCode())) { return null; } /*19年不含税金额:24268.88 已摊销天数:161 20不含税金额:31202.8181132075 未摊销天数:205 合同日期2019.7.24-2020.7.23, 合同编号:QQ-ADI-20190729-57*/ DateTime[] middlePoiont = new DateTime[]{new DateTime("2019-12-31"), new DateTime("2020-01-01")}; contract.setAdjustmentFund(0L); contract.setIncomeExcludingTax(new BigDecimal(24268.88 * 100).add(new BigDecimal(31202.8181132075 * 100)) .setScale(2, BigDecimal.ROUND_HALF_UP).longValue()); BigDecimal dayShare_19 = new BigDecimal(24268.88).multiply(new BigDecimal(100)) .divide(new BigDecimal(161), 15, BigDecimal.ROUND_HALF_UP); //选择时间范围内 20 年分摊天数 及每天分摊 BigDecimal dayShare_20 = new BigDecimal(31202.8181132075).multiply(new BigDecimal(100)) .divide(new BigDecimal(205), 15, BigDecimal.ROUND_HALF_UP); if (checkTwoTime(usePart[0], middlePoiont[0]) && checkTwoTime(middlePoiont[1], usePart[1])) { //选择时间范围内 19 + 20 年分摊天数 及每天分摊 Long allDayShare = dayShare_19.multiply(new BigDecimal(getDayRange(usePart[0], middlePoiont[0]) + 1)) .add(dayShare_20.multiply(new BigDecimal(getDayRange(middlePoiont[1], usePart[1]) + 1))) .setScale(2, BigDecimal.ROUND_HALF_UP).longValue(); contract.setIntervaIncomeShare(allDayShare); } else { int days = getDayRange(usePart[0], usePart[1]) + 1; if (checkTwoTime(usePart[1], middlePoiont[0])) { //19 年 contract.setIntervaIncomeShare(shareMultiply(dayShare_19, new BigDecimal(days), 2)); } else { //20 年 contract.setIntervaIncomeShare(shareMultiply(dayShare_20, new BigDecimal(days), 2)); } } contract.setIncomeShareAll(contract.getIntervaIncomeShare()); return contract; } private void afterContract(Contract contract, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected, DateTime[] creatPoints) { int betweenMonth = Months.monthsBetween(contractPart[0], creatPoints[0]).getMonths(); //时间范围内用于计算分摊金额的天数 int daysIncom = getDayRange(usePart[0], usePart[1]) + 1; //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); Long adjustmentFund = 0L;//调整金 boolean isLateContract = false; // 是否为晚录合同(为了兼容历史数据 此处做冗余判断) if (ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) { isLateContract = true; } else if (checkLateContract(contractPart[0], creatPoints[0])) { isLateContract = true; } if (isLateContract) { contract.setStatus(ContractStatusEnum.LATE.getKey()); } boolean isLater = true; if (!isLateContract || betweenMonth < 1) { //非合同晚录 contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); isLater = false; } else if (selected[1].isBefore(creatPoints[1])) { //录入月1号之前 调整金为 0 分摊为 0 contract.setIntervaIncomeShare(0L); contract.setAdjustmentFund(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare()); contract.setStatus(ContractStatusEnum.LATE.getKey()); } else { contract.setStatus(ContractStatusEnum.LATE.getKey()); //合同晚录 //所选时间范围内的分摊收入(录入月1号 即creatPoints[1] 开始计算) DateTime useStart = creatPoints[1].compareTo(selected[0]) >= 0 ? creatPoints[1] : selected[0]; daysIncom = getDayRange(useStart, usePart[1]) + 1; contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); adjustmentFund = shareMultiply(dayShareIncome, new BigDecimal(getDayRange(contractPart[0], creatPoints[1].plusDays(-1)) + 1), 0); if (checkTwoTime(selected[0], creatPoints[1]) && checkTwoTime(creatPoints[1], selected[1])) { //所选时间范围包含 录入月 1 号 显示统计的调整金 contract.setAdjustmentFund(adjustmentFund); } else { contract.setAdjustmentFund(0L); } } if (checkTwoTime(selected[0], contractPart[1]) && checkTwoTime(contractPart[1], selected[1])) { contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractPart[0], contractPart[1]) + 1), dayShareIncome, 0)); } else { contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractPart[0], selected[1]) + 1), dayShareIncome, 0)); } if (checkTwoTime(contractPart[1], selected[1])) { //最后一日分摊金计算处理 Long lastDay; if (isLater) { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome, new BigDecimal(getDayRange(creatPoints[1], contractPart[1])), 0); } else { lastDay = contract.getIncomeExcludingTax() - adjustmentFund - shareMultiply(dayShareIncome, new BigDecimal(getDayRange(contractPart[0], contractPart[1])), 0); } //最后一日 或 包含最后一日 时 contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - dayShareIncome.setScale(0, BigDecimal.ROUND_HALF_UP).longValue() + lastDay); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); } private Contract suspendShare(Contract contract, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.SUSPEND.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); return contract; } // 合同终止日 或 作废日 DateTime cancelDate = new DateTime(contractChange.getDs()); //中止操作入库时间 DateTime suspendDate = new DateTime(new DateTime(contractChange.getCreateTime()).toString("yyyy-MM-dd")); Long adjustmentFund = 0L; if (checkTwoTime(suspendDate, cancelDate)) { adjustmentFund = 0L; } else { adjustmentFund = shareMultiply(new BigDecimal((getDayRange(cancelDate, suspendDate) + 1) * -1), dayShareIncome, 0); } DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; int daysIncom = Days.daysBetween(usePart[0], usedEnd).getDays() + 1; daysIncom = daysIncom < 0 ? 0 : daysIncom; //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { contract.setAdjustmentFund(adjustmentFund); contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractPart[0], cancelDate) + 1), dayShareIncome, 0)); } else { contract.setAdjustmentFund(0L); contract.setIncomeGross(shareMultiply(new BigDecimal(getDayRange(contractPart[0], selected[1]) + 1), dayShareIncome, 0)); } contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); return contract; } private Contract cancledShare(Contract contract, int contractAllDay, BigDecimal dayShareIncome, DateTime[] contractPart, DateTime[] usePart, DateTime[] selected) { if (!ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus())) { return null; } ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode()); if (contractChange == null) { contract.setAdjustmentFund(0L); contract.setIntervaIncomeShare(0L); contract.setIncomeShareAll(0L); return contract; } // 合同终止日 或 作废日 DateTime cancelDate = new DateTime(contractChange.getDs()); Long adjustmentFund = shareMultiply(new BigDecimal((getDayRange(contractPart[0], cancelDate) + 1) * -1), dayShareIncome, 0); DateTime usedEnd = usePart[1].compareTo(cancelDate) <= 0 ? usePart[1] : cancelDate; int daysIncom = Days.daysBetween(usePart[0], usedEnd).getDays() + 1; daysIncom = daysIncom < 0 ? 0 : daysIncom; contract.setIntervalUseDays(getDayRange(contractPart[0], usedEnd) + 1); //区间分摊总收入 contract.setIntervaIncomeShare(shareMultiply(dayShareIncome, new BigDecimal(daysIncom), 0)); if (checkTwoTime(selected[0], cancelDate) && checkTwoTime(cancelDate, selected[1])) { contract.setAdjustmentFund(adjustmentFund); } else { contract.setAdjustmentFund(0L); } contract.setIncomeGross(0L); contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund()); return contract; } private Long shareMultiply(BigDecimal one, BigDecimal two, int scale) { return one.multiply(two).setScale(scale, BigDecimal.ROUND_HALF_UP).longValue(); } @Override public boolean checkLateContract(DateTime dateTime, DateTime creatTime) { //int aferDays = dateTime.monthOfYear().get() == 12 ? 29 : 9; //修改晚录判断逻辑 int aferDays = dateTime.monthOfYear().get() == 12 ? 29 : 1; return dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays).isBefore(creatTime); } private int getDayRange(DateTime range1, DateTime range2) { return Days.daysBetween(range1, range2).getDays(); } public boolean checkTwoTime(DateTime dateTime1, DateTime dateTime2) { return dateTime1.isBefore(dateTime2) || dateTime1.isEqual(dateTime2); } @Override public List<TrackFlowVO> trialFlow(User loginAccount, String startDate, String endDate, String platform, String email) { //离线数据值 Map<String, Double> offlineResult = tkioOfflineRepository.findOfflineResult(startDate, endDate); //查询主账号 List<Map<String, String>> list = null; if (StringUtil.isEmpty(email)) { list = accountRepository.findAllAccountAppKeys(); } else { list = accountRepository.findAccountAppKeysByEmail(email); } JSONArray jsonObject = JSONArray.fromObject(list); Iterator it = jsonObject.iterator(); List<AccountVO> avs = new ArrayList<>(); while (it.hasNext()) { JSONArray array = JSONArray.fromObject(it.next()); String e = array.getString(0); String k = array.getString(1); AccountVO vo = new AccountVO(); vo.setEmail(e); vo.setAppKey(k); avs.add(vo); } //汇总计算 List<TrackFlowVO> result = new ArrayList<>(); for (AccountVO ac : avs) { TrackFlowVO tf = new TrackFlowVO(ac.getEmail()); String appKeys = ac.getAppKey(); //如果appKey为空,流量为0 if ("".equals(appKeys.trim())) { tf.setTrackFlow(0.0); result.add(tf); continue; } Double sum = 0.0; String[] keyArr = appKeys.split(","); for (String k : keyArr) { Double v = offlineResult.get(k); if (v == null) { v = 0.0; } sum += v; } tf.setTrackFlow(new BigDecimal(sum / 10000).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); result.add(tf); } return result; } public static void main(String[] args) { DateTime dateTime = new DateTime("2020-10-30"); DateTime creatTime = new DateTime("2020-11-02"); int aferDays = dateTime.monthOfYear().get() == 12 ? 29 : 1; System.out.println("合同开始时间" + dateTime); System.out.println("合同录入时间" + creatTime); System.out.println("合同开始时间在第" + dateTime.monthOfYear().get() + "月"); System.out.println("合同录入当月的最后一天日期:" + dateTime.dayOfMonth().withMaximumValue()); System.out.println("合同录入当月的最后一天日期后第" + aferDays + "天" + dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays)); System.out.println("是否是晚录:" + dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays).isBefore(creatTime)); dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays).isBefore(creatTime); } public static void main2(String[] args) { DateTime contractStart = new DateTime("2020-05-15"); DateTime create = new DateTime("2020-06-15"); System.out.println(contractStart.monthOfYear().getDateTime()); System.out.println(contractStart.dayOfMonth().withMaximumValue().plusDays(1)); System.out.println(contractStart.dayOfMonth().withMaximumValue().plusDays(9).isBefore(create)); System.out.println(contractStart.compareTo(create)); long ss = new BigDecimal(94000 * 1.0 / 52) .setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); System.out.println(ss); DateTime[][] times = new DateTime[][]{ {new DateTime(), new DateTime()}, {new DateTime(), new DateTime()} }; System.out.println(times[1][0].toString()); } }