|
|
|
|
@ -2,16 +2,14 @@ package com.biutag.supervision.service;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.util.NumberUtil; |
|
|
|
|
import com.biutag.supervision.constants.enums.BusinessTypeEnum; |
|
|
|
|
import com.biutag.supervision.pojo.entity.BusinessPolice; |
|
|
|
|
import com.biutag.supervision.pojo.entity.NegativeScorePolice; |
|
|
|
|
import com.biutag.supervision.pojo.entity.SupPolice; |
|
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal; |
|
|
|
|
import java.time.LocalDateTime; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Date; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.*; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -32,6 +30,10 @@ public class ProfilePoliceService {
|
|
|
|
|
|
|
|
|
|
private final NegativeScorePoliceService negativeScorePoliceService; |
|
|
|
|
|
|
|
|
|
private final BusinessPoliceService businessPoliceService; |
|
|
|
|
|
|
|
|
|
private final SupPoliceService policeService; |
|
|
|
|
|
|
|
|
|
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
|
|
|
|
|
public double getBusinessWeight(Double totalScore, List<NegativeScorePolice> businessScorePolice) { |
|
|
|
|
if (totalScore == 0) { |
|
|
|
|
@ -58,8 +60,29 @@ public class ProfilePoliceService {
|
|
|
|
|
return Math.sqrt(group.values().stream().mapToDouble(val -> Math.pow(val.size() - avgNumber, 2)).sum() / policeSize); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 业务差异值1 = (个人问题发生率 - 平均问题发生率) / 业务标准差
|
|
|
|
|
// 平均问题发生率 = 总问题数 / 总业务量
|
|
|
|
|
// 个人问题发生率 = 个人问题数 / 个人业务量
|
|
|
|
|
public double getDiff1(List<NegativeScorePolice> businessScorePolice, SupPolice police, Date beginTime, Date endTime, String businessTypeCode, double sd) { |
|
|
|
|
if (sd == 0) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
List<BusinessPolice> businessPolices = businessPoliceService.list(beginTime, endTime, businessTypeCode); |
|
|
|
|
// 总业务量
|
|
|
|
|
int totalBusinessSize = businessPolices.stream().mapToInt(BusinessPolice::getNumber).sum(); |
|
|
|
|
// 平均问题发生率
|
|
|
|
|
double avgRate = totalBusinessSize == 0? 0: NumberUtil.div(businessScorePolice.size(), totalBusinessSize); |
|
|
|
|
// 个人问题数
|
|
|
|
|
long personSize = businessScorePolice.stream().filter(item -> police.getIdCode().equals(item.getIdCode())).count(); |
|
|
|
|
// 个人业务量
|
|
|
|
|
long personBusinessSize = businessPolices.stream().filter(item -> police.getName().equals(item.getPoliceName()) && police.getEmpNo().equals(item.getEmpNo())).count(); |
|
|
|
|
// 个人问题发生率
|
|
|
|
|
double personRate = personBusinessSize == 0? 0: NumberUtil.div(personSize, personBusinessSize); |
|
|
|
|
return NumberUtil.div(personRate - avgRate, sd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 业务差异值2 = (问题数 - 平均问题数) / 业务标准差
|
|
|
|
|
public double getDiff(List<NegativeScorePolice> businessScorePolice, String idCode, double avgNumber, double sd) { |
|
|
|
|
public double getDiff2(List<NegativeScorePolice> businessScorePolice, String idCode, double avgNumber, double sd) { |
|
|
|
|
if (sd == 0) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
@ -67,6 +90,7 @@ public class ProfilePoliceService {
|
|
|
|
|
return NumberUtil.div(size - avgNumber, sd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public double getBusinessScore(double diff) { |
|
|
|
|
return 50 + (diff * 15); |
|
|
|
|
} |
|
|
|
|
@ -79,9 +103,11 @@ public class ProfilePoliceService {
|
|
|
|
|
// 业务风险指数 = 50 + (业务差异值 * 15)
|
|
|
|
|
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
|
|
|
|
|
// 个人风险指数 = sum(业务风险指数 * 业务权重)
|
|
|
|
|
public BigDecimal getPoliceScore(Date beginTime, Date endTime, String idCode) { |
|
|
|
|
public List<Object> getPoliceScore(Date beginTime, Date endTime, String idCode) { |
|
|
|
|
List<NegativeScorePolice> scorePolices = negativeScorePoliceService.list(beginTime, endTime); |
|
|
|
|
Double totalScore = scorePolices.stream().mapToDouble(NegativeScorePolice::getScore).sum(); |
|
|
|
|
SupPolice police = policeService.getByIdCode(idCode); |
|
|
|
|
List<String> expressionArr = new ArrayList<>(); |
|
|
|
|
double policeScore = Arrays.stream(BusinessTypeEnum.values()).mapToDouble(businessTypeEnum -> { |
|
|
|
|
List<NegativeScorePolice> businessScorePolice = scorePolices.stream().filter(item -> item.getBusinessTypeCode().equals(businessTypeEnum.getValue())).toList(); |
|
|
|
|
// 业务涉及人数
|
|
|
|
|
@ -91,19 +117,22 @@ public class ProfilePoliceService {
|
|
|
|
|
// 业务标准差
|
|
|
|
|
double sd = getSd(businessScorePolice, avgNumber, policeSize); |
|
|
|
|
// 业务差异值
|
|
|
|
|
double diff = 0; |
|
|
|
|
double diff; |
|
|
|
|
if (businessTypeEnum.getBusinessVolume()) { |
|
|
|
|
|
|
|
|
|
diff = getDiff1(businessScorePolice, police, beginTime, endTime, businessTypeEnum.getValue(), sd); |
|
|
|
|
} else { |
|
|
|
|
diff = getDiff(businessScorePolice, idCode, avgNumber, sd); |
|
|
|
|
diff = getDiff2(businessScorePolice, idCode, avgNumber, sd); |
|
|
|
|
} |
|
|
|
|
// 业务风险指数
|
|
|
|
|
double businessScore = getBusinessScore(diff); |
|
|
|
|
// 业务权重
|
|
|
|
|
double businessWeight = getBusinessWeight(totalScore, businessScorePolice); |
|
|
|
|
expressionArr.add(String.format("(%s * %s)", businessScore, businessWeight)); |
|
|
|
|
return NumberUtil.mul(businessScore, businessWeight); |
|
|
|
|
}).sum(); |
|
|
|
|
return NumberUtil.roundHalfEven(policeScore, 2); |
|
|
|
|
BigDecimal score = NumberUtil.roundHalfEven(policeScore, 2); |
|
|
|
|
String expression = String.join(" + ", expressionArr); |
|
|
|
|
return List.of(score, expression); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|