Commit e189e008 by lzxry

tkio分摊计算2.0

parent 787093b6
......@@ -74,7 +74,6 @@ public class Contract {
private List<String> customBodyNames;
/**
* 新增字段 20190427
*/
......@@ -97,6 +96,11 @@ public class Contract {
private Double trackFlow;//流量,tkio的,万单位
private Double unitPrice;//单价,tkio
private Double clickFlow;//区间点击数,tkio
private String nextSignedDate;//绑定下一份合同的日期
private String nextSignedContractCode;//绑定的下一份合同编号
private String signedDate;//合同签订日:补充协议才有值
private double historyTkioFlow;//万单位,保留四位
private BigDecimal unitPriceAccurate;//16位的单价
@Id
@GeneratedValue
......@@ -606,6 +610,48 @@ public class Contract {
this.incomeGross = incomeGross;
}
public String getNextSignedDate() {
return nextSignedDate;
}
public void setNextSignedDate(String nextSignedDate) {
this.nextSignedDate = nextSignedDate;
}
public String getNextSignedContractCode() {
return nextSignedContractCode;
}
public void setNextSignedContractCode(String nextSignedContractCode) {
this.nextSignedContractCode = nextSignedContractCode;
}
public String getSignedDate() {
return signedDate;
}
public void setSignedDate(String signedDate) {
this.signedDate = signedDate;
}
@Transient
public double getHistoryTkioFlow() {
return historyTkioFlow;
}
public void setHistoryTkioFlow(double historyTkioFlow) {
this.historyTkioFlow = historyTkioFlow;
}
@Transient
public BigDecimal getUnitPriceAccurate() {
return unitPriceAccurate;
}
public void setUnitPriceAccurate(BigDecimal unitPriceAccurate) {
this.unitPriceAccurate = unitPriceAccurate;
}
@Override
public String toString() {
return "Contract{" +
......@@ -650,6 +696,7 @@ public class Contract {
", incomeExcludingTax=" + incomeExcludingTax +
", intervaIncomeShare=" + intervaIncomeShare +
", incomeShareAll=" + incomeShareAll +
", incomeGross=" + incomeGross +
", shareSign=" + shareSign +
", searchName='" + searchName + '\'' +
", customBodyNames=" + customBodyNames +
......@@ -664,7 +711,16 @@ public class Contract {
", erroMessage='" + erroMessage + '\'' +
", tradeName='" + tradeName + '\'' +
", barrioId=" + barrioId +
", barrioName='" + barrioName + '\'' +
", belongGroup='" + belongGroup + '\'' +
", trackFlow=" + trackFlow +
", unitPrice=" + unitPrice +
", clickFlow=" + clickFlow +
", nextSignedDate='" + nextSignedDate + '\'' +
", nextSignedContractCode='" + nextSignedContractCode + '\'' +
", signedDate='" + signedDate + '\'' +
", historyTkioFlow=" + historyTkioFlow +
", unitPriceAccurate=" + unitPriceAccurate +
'}';
}
}
package common.model;
import java.util.List;
/**
* @author liyin
* @description
* @date
*/
public class ContractVO {
private Contract master;
private List<Contract> sideLette;
public Contract getMaster() {
return master;
}
public void setMaster(Contract master) {
this.master = master;
}
public List<Contract> getSideLette() {
return sideLette;
}
public void setSideLette(List<Contract> sideLette) {
this.sideLette = sideLette;
}
@Override
public String toString() {
return "ContractVO{" +
"master=" + master +
", sideLette=" + sideLette +
'}';
}
}
......@@ -9,6 +9,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
......@@ -57,7 +58,7 @@ public interface ContractRepository extends JpaRepository<Contract, Long> {
@Query(value = "select new map( c.id as id, c.contractCode as contractCode ) from Contract c where c.platform in ?1 and c.contractCode is not null and c.contractCode <> 'null' and c.status <>'del'")
List<Map> contractCodePlatform(List<String> platform);
@Query(value = "select * from contract where platform = ?1 and contract_code = ?2", nativeQuery = true)
@Query(value = "select * from contract where platform = ?2 and contract_code = ?1", nativeQuery = true)
Contract findByCodePlatform(String contractCode, String platform);
@Query(value = "select * from contract where start_date >= ?1 and start_date <= ?2 and platform in ?3 and id in ?4 and status!='del' order by ds desc", nativeQuery = true)
......@@ -128,4 +129,10 @@ public interface ContractRepository extends JpaRepository<Contract, Long> {
@Query(value = "SELECT * from contract where platform = ?1 and email = ?2", nativeQuery = true)
List<Contract> findByPlatformAndEmail(String platform, String email);
@Query(value = "SELECT * from contract where (contract_code = ?1 or relation_code = ?1) and create_time <= ?2 and id<> ?3 and contract_type <> '1'", nativeQuery = true)
List<Contract> findByCreateTimeAndCodeNotOwn(String contractCode, String createTime,Long id);
@Query(value = "select * from contract where next_signed_contract_code=?1 limit 1 ",nativeQuery = true)
Contract findByNextSignedContractCode(String contractCode);
}
......@@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
public interface TkioFlowRepository extends JpaRepository<TkioFlow, Long> {
......@@ -20,4 +21,7 @@ public interface TkioFlowRepository extends JpaRepository<TkioFlow, Long> {
@Query(value = "select sum(flow) from tkio_flow where contract_code = ?1 and ds >= ?2 and ds <= ?3", nativeQuery = true)
BigDecimal sumFlowByContractCodeAndDs(String code, String startDate, String endDate);
@Query(value = "select sum(flow) from tkio_flow where contract_code in ?3 and ds >= ?1 and ds <= ?2", nativeQuery = true)
BigDecimal sumFlowByDsAndContractCodes(String startDate, String endDate, ArrayList<String> contractCode);
}
......@@ -588,8 +588,38 @@ public class ContractServiceImpl implements ContractService {
}
}
calculationFlowRepository.save(calculationFlow);
//补充协议:后端逻辑顺序绑定
if("2".equals(resource.getContractType())){
DateTime dateTime = new DateTime(resource.getSignedDate());//补充协议晚录判断
if (shareIncomeService.checkLateContract(dateTime,
new DateTime(new DateTime().toString("yyyy-MM-dd")))) {
resource.setStatus(ContractStatusEnum.LATE.getKey());
}
String relationCode = resource.getRelationCode();
String platform = resource.getPlatform();
while(true){
Contract contract = contractRepository.findByCodePlatform(relationCode, platform);
if(StringUtils.isEmpty(contract.getNextSignedDate())){
if(ContractStatusEnum.LATE.getKey().equals(resource.getStatus())){//如果晚录则设置绑定下一份合同的日期为签订月的最后一天
contract.setNextSignedDate(dateTime.dayOfMonth().withMaximumValue().toString("yyyy-MM-dd"));
}else{
contract.setNextSignedDate(dateTime.plusDays(-1).toString("yyyy-MM-dd"));//签订日的前一天
}
contract.setNextSignedContractCode(resource.getContractCode());
contractRepository.save(contract);
break;
}else{
relationCode = contract.getNextSignedContractCode();
}
}
}
}
resource = contractRepository.save(resource);
......@@ -888,13 +918,24 @@ public class ContractServiceImpl implements ContractService {
}
resource.setStatus(contract.getStatus());
if (ContractStatusEnum.NFORMAL.getKey().equals(contract.getStatus()) || ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) {
if (shareIncomeService.checkLateContract(new DateTime(resource.getStartDate()),
new DateTime(new DateTime(resource.getCreateTime()).toString("yyyy-MM-dd")))) {
resource.setStatus(ContractStatusEnum.LATE.getKey());
}else{
resource.setStatus(ContractStatusEnum.NFORMAL.getKey());
}
}
//this.calculateShareIncome(resource);
resource.setId(contract.getId());
//判断库里是否已有合同的主账号
if ("tkio".equals(resource.getPlatform()) && (contract.getStartDate() != resource.getStartDate() && contract.getEndDate() != resource.getEndDate())) {
if ("tkio".equals(resource.getPlatform())) {
if(contract.getStartDate() != resource.getStartDate() && contract.getEndDate() != resource.getEndDate()) {
List<Contract> contracts = contractRepository.findByPlatformAndEmail(resource.getPlatform(), resource.getEmail());
CalculationFlow calculationFlow = new CalculationFlow();
calculationFlow.setEmail(resource.getEmail());
......@@ -915,6 +956,26 @@ public class ContractServiceImpl implements ContractService {
}
calculationFlowRepository.save(calculationFlow);
}
//补充协议
if("2".equals(resource.getContractType())){
DateTime dateTime = new DateTime(resource.getSignedDate());//补充协议晚录判断
if (ContractStatusEnum.NFORMAL.getKey().equals(contract.getStatus()) || ContractStatusEnum.LATE.getKey().equals(contract.getStatus())) {
if (shareIncomeService.checkLateContract(dateTime,
new DateTime(new DateTime(resource.getCreateTime()).toString("yyyy-MM-dd")))) {
resource.setStatus(ContractStatusEnum.LATE.getKey());
}else{
resource.setStatus(ContractStatusEnum.NFORMAL.getKey());
}
}
Contract bindContract = contractRepository.findByNextSignedContractCode(resource.getContractCode());
if(ContractStatusEnum.LATE.getKey().equals(resource.getStatus())){//如果晚录则设置绑定下一份合同的日期为签订月的最后一天
bindContract.setNextSignedDate(dateTime.dayOfMonth().withMaximumValue().toString("yyyy-MM-dd"));
}else{
bindContract.setNextSignedDate(dateTime.plusDays(-1).toString("yyyy-MM-dd"));//签订日的前一天
}
contractRepository.save(bindContract);
}
}
return contractRepository.save(resource);
......
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;
......@@ -7,28 +10,26 @@ import dic.ContractStatusEnum;
import dic.RoleEnum;
import net.sf.json.JSONArray;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormatter;
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.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
......@@ -125,14 +126,25 @@ public class ShareIncomeServiceImpl implements ShareIncomeService {
// 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)){
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()==20){
if(v.getPriceLevel()==Constant.tkioPriceLevelNotLimit){
//TKIO不限量套餐
this.shareIncome4Contract(v, start, end);
}else{
......@@ -143,18 +155,468 @@ public class ShareIncomeServiceImpl implements ShareIncomeService {
break;
default:this.shareIncome4Contract(v, start, end);break;
}
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());
});
}
}
logger.info("计算分摊收入耗时:{}", (System.currentTimeMillis() - start_));
return contracts;
}
/**
* 功能描述:增加补充协议的逻辑
* @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 -> {
multimap.put(v.getEmail(),v);
});
}
//遍历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())){
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) {
map.put(contract1.getContractCode(),contract1);
}
groupContracts = map.values();//只要不加入传进来的那个list里面就不会影响查询的列表
}
}
}
//再次进行合同的关系分组--->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);
}
}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);
}
//补充协议核心逻辑
if(isNotLimit){//无限流量
//能运行到这里说明只有补充协议才会出现无限流量(最后一个),如果是主合同无限流量,就不可能有补充协议
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+=contractsArray[j].getMoney();
double currentFlow = contractsArray[j].getTrackFlow()+accruingFlow;
double currentMoney = contractsArray[j].getMoney()+accruingAmounts;
contractsArray[j].setUnitPriceAccurate(new BigDecimal(currentMoney / 1.06 / currentFlow)
.setScale(16, BigDecimal.ROUND_HALF_UP));//存储16位单价
accruingAmounts+= new BigDecimal(currentMoney/1.06/currentFlow*contractsArray[j].getHistoryTkioFlow())
.setScale(16, BigDecimal.ROUND_HALF_UP).doubleValue();//当前合同之前的累计消耗金额
accruingFlow+=contractsArray[j].getHistoryTkioFlow();//当前合同之前的累计消耗流量,万单位
}
totalFlow=totalFlow-accruingFlow+contract.getTrackFlow();
totalprice=totalprice-accruingAmounts+contract.getMoney();
BigDecimal unitPriceAccurate = new BigDecimal(totalprice/1.06/totalFlow)
.setScale(16, BigDecimal.ROUND_HALF_UP);//当前合同的单价
//四舍五入单价
double unitPrice = unitPriceAccurate.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
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(!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());
}
BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(usePart[0].toString("yyyy-MM-dd"), usePart[1].toString("yyyy-MM-dd"), codes);
int clickFlow = clickNum == null ? 0 : clickNum.intValue();
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 ? 0 : clickNum.intValue();
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);
int clickFlow = clickNum==null?0:clickNum.intValue();
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?0:clickNum.intValue();
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 ? 0 : clickNum.intValue();
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);
int clickFlow = clickNum==null?0:clickNum.intValue();
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?0:clickNum.intValue();
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 / 1.06)
.setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100L)).longValue();
//TODO 超出的流量算在了调整金了这里好像减去了
lastDay = excludTax - contract.getAdjustmentFund() - beforeTheMoney;
//最后一日 或 包含最后一日 时
contract.setIntervaIncomeShare(contract.getIntervaIncomeShare() - lastDayTheMoney + lastDay);
}
contract.setIncomeShareAll(contract.getIntervaIncomeShare() + contract.getAdjustmentFund());
}else{//不限量套餐
int contractAllDay = getDayRange(contractPart[0], contractPart[1]) + 1;//合同总天数
BigDecimal dayShareIncome = new BigDecimal(totalprice/1.06/contractAllDay)
.setScale(16, BigDecimal.ROUND_HALF_UP);
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;//调整金
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);
}
ArrayList<String> codes = new ArrayList<>();
for (int k = 0; k <= i; k++) {
codes.add(contractsArray[k].getContractCode());
}
//处理上一份合同
BigDecimal clickNum = tkioFlowRepository.sumFlowByDsAndContractCodes(contractPart[0].toString("yyyy-MM-dd"), creatPoints[1].plusDays(-1).toString("yyyy-MM-dd"), codes);
int clickFlow = clickNum==null?0:clickNum.intValue();
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(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());
}
}
}else{
Contract contractMaster = contractsArray[i];
if(contracts.contains(contractMaster)){
Contract nextContract = contractsArray[i + 1];
shareIncome4ContractTKIO(contractMaster,start,new DateTime(nextContract.getNextSignedDate()));//到结束的前一天
}
}
}
}else{//普通流量
}
}
}
//多个合同其中有一个无限流量的,这组全部都走adi逻辑,否则用新需求的逻辑计算
}
}
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;
}
}
}
return contractsArray;
}
private void shareIncome4ContractTKIO(Contract contract, DateTime start, DateTime end) {
DateTime[] selected = new DateTime[]{
start,
......@@ -171,10 +633,14 @@ public class ShareIncomeServiceImpl implements ShareIncomeService {
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位数
BigDecimal unitPriceAccurate = new BigDecimal(contract.getMoney()/1.06/contract.getTrackFlow())
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();
//不限量套餐会在方法里面重新赋值单价
......@@ -561,7 +1027,6 @@ public class ShareIncomeServiceImpl implements ShareIncomeService {
if(clickFlow!=0){
clickTenThousand = new BigDecimal(clickFlow / 10000.0 * 100);
//区间点击数
System.out.println(new BigDecimal(clickFlow / 10000.0));
contract.setClickFlow(new BigDecimal(clickFlow / 10000.0).setScale(4,BigDecimal.ROUND_HALF_UP).doubleValue());
}
//区间分摊收入
......@@ -1029,7 +1494,14 @@ public class ShareIncomeServiceImpl implements ShareIncomeService {
}
public static void main(String[] args) {
System.out.println(new BigDecimal(34009003 / 10000.0));
DateTime dateTime = new DateTime("2020-10-30");
DateTime creatTime = new DateTime("2020-11-9");
int aferDays = dateTime.monthOfYear().get() == 12 ? 29 : 9;
System.out.println(dateTime.monthOfYear().get());
System.out.println(dateTime.dayOfMonth().withMaximumValue());
System.out.println(dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays));
System.out.println(dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays).isBefore(creatTime));
dateTime.dayOfMonth().withMaximumValue().plusDays(aferDays).isBefore(creatTime);
}
......
......@@ -35,6 +35,7 @@ public class Constant {
public static String dbusername = resourceBundle.getString("db.username");
public static String dbpassword = resourceBundle.getString("db.password");
public static String dbdriver = resourceBundle.getString("db.driver");
public static Long tkioPriceLevelNotLimit = 20L;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment