@ -11,7 +11,6 @@ import com.biutag.supervision.pojo.entity.*;
import com.biutag.supervision.util.ScoreRule ;
import lombok.RequiredArgsConstructor ;
import lombok.extern.slf4j.Slf4j ;
import org.springframework.scheduling.annotation.Async ;
import org.springframework.stereotype.Service ;
import java.math.BigDecimal ;
@ -116,90 +115,77 @@ public class NegativeScoreService {
System . out . println ( "calculateScore-------------------------------------------------End" ) ;
}
private final BusinessPoliceService businessPoliceService ;
private final BusinessDepartService businessDepartService ;
private final SupPoliceService policeService ;
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
public double calculateBusinessWeight ( Double totalScore , Double s core) {
public double calculateBusinessWeight ( Double score , Double totalS core) {
if ( totalScore = = 0 ) {
return 0 . 0 ;
}
log . info ( "业务权重 = {} / {}" , score , totalScore ) ;
return NumberUtil . div ( score , totalScore ) ;
}
// 平均问题数 = 单个业务问题数 / 业务涉及人数
public double calculateAvgNumber ( int size , int policeSize ) {
if ( policeSize = = 0 ) {
// 平均问题发生率 = 单个业务问题加权数 / 单位总业务量
public double calculateAvgNumber ( double businessWeightScore , int totalBusinessSize ) {
if ( totalBusinessSize = = 0 ) {
log . info ( "平均问题发生率 = 0" ) ;
return 0 ;
}
return NumberUtil . div ( size , policeSize ) ;
log . info ( "平均问题发生率 = {} / {}" , businessWeightScore , totalBusinessSize ) ;
return NumberUtil . div ( businessWeightScore , totalBusinessSize ) ;
}
// 业务标准差 = 根号(sum((个人问题数 - 平均问题数)²) / 业务涉及人数)
public double calculateSd ( double [ ] diffNumber , int policeSize ) {
public double calculateSd1 ( double [ ] diffNumber , int policeSize ) {
if ( policeSize = = 0 ) {
log . info ( "业务标准差 = 0" ) ;
return 0 ;
}
log . info ( "业务标准差 = 根号({}) / {}" , Arrays . stream ( diffNumber ) . mapToObj ( val - > String . format ( "(%s)²" , val ) ) . collect ( Collectors . joining ( " + " ) ) , policeSize ) ;
return Math . sqrt ( Arrays . stream ( diffNumber ) . map ( val - > Math . pow ( val , 2 ) ) . sum ( ) / policeSize ) ;
}
// 业务差异值1 = (个人问题发生率 - 平均问题发生率) / 业务标准差
// 平均问题发生率 = 总问题数 / 总业务量
// 个人问题发生率 = 个人问题数 / 个人业务量
public double calculateDiff1 ( List < NegativeScorePolice > businessScorePolice , SupPolice police , Date beginTime , Date endTime , String businessTypeCode , double sd ) {
if ( sd = = 0 ) {
// 业务标准差 = 根号(sum((个人问题数 - 平均问题数)²) / 业务涉及人数)
public double calculateSd2 ( double [ ] diffNumber , int policeSize ) {
if ( policeSize = = 0 ) {
log . info ( "业务标准差 = 0" ) ;
return 0 ;
}
List < BusinessDepart > businessDeparts = businessDepartService . list ( beginTime , endTime , businessTypeCode ) ;
// 总业务量
int totalBusinessSize = businessDeparts . stream ( ) . mapToInt ( BusinessDepart : : getNumber ) . sum ( ) ;
// 平均问题发生率
double avgRate = totalBusinessSize = = 0 ? 0 : NumberUtil . div ( businessScorePolice . size ( ) , totalBusinessSize ) ;
// 个人问题数
long personSize = businessScorePolice . stream ( ) . filter ( item - > police . getOrgId ( ) . equals ( item . getIdCode ( ) ) ) . count ( ) ;
// 单位业务量
long departBusinessSize = businessDeparts . stream ( ) . filter ( item - > police . getOrgId ( ) . equals ( item . getDepartId ( ) ) ) . count ( ) ;
// 个人问题发生率
double personRate = departBusinessSize = = 0 ? 0 : NumberUtil . div ( personSize , departBusinessSize ) ;
return NumberUtil . div ( personRate - avgRate , sd ) ;
log . info ( "业务标准差 = 根号({}) / {}" , Arrays . stream ( diffNumber ) . mapToObj ( val - > String . format ( "(%s)²" , val ) ) . collect ( Collectors . joining ( " + " ) ) , policeSize ) ;
return Math . sqrt ( Arrays . stream ( diffNumber ) . map ( val - > Math . pow ( val , 2 ) ) . sum ( ) / policeSize ) ;
}
public double calculateDiff1ByDepart ( List < NegativeScoreDepart > businessScoreDeparts , String departId , Date beginTime , Date endTime , String businessTypeCode , double sd ) {
// 业务差异值1 = (个人问题发生率 - 平均问题发生率) / 业务标准差
// 平均问题发生率 = 总问题数 / 总业务量
// 个人问题发生率 = 个人问题数 / 个人业务量
public double calculateDiff1 ( double personalRate , double avgNumber , double sd ) {
if ( sd = = 0 ) {
log . info ( "业务差异值(发生率) = 0" ) ;
return 0 ;
}
List < BusinessDepart > businessDeparts = businessDepartService . list ( beginTime , endTime , businessTypeCode ) ;
// 总业务量
int totalBusinessSize = businessDeparts . stream ( ) . mapToInt ( BusinessDepart : : getNumber ) . sum ( ) ;
// 平均问题发生率
double avgRate = totalBusinessSize = = 0 ? 0 : NumberUtil . div ( businessScoreDeparts . size ( ) , totalBusinessSize ) ;
// 个人问题数
long personSize = businessScoreDeparts . stream ( ) . filter ( item - > departId . equals ( item . getDepartId ( ) ) ) . count ( ) ;
// 个人业务量
long personBusinessSize = businessDeparts . stream ( ) . filter ( item - > departId . equals ( item . getDepartId ( ) ) ) . count ( ) ;
// 个人问题发生率
double personRate = personBusinessSize = = 0 ? 0 : NumberUtil . div ( personSize , personBusinessSize ) ;
return NumberUtil . div ( personRate - avgRate , sd ) ;
log . info ( "业务差异值(发生率) = ({} - {}) / {}" , personalRate , avgNumber , sd ) ;
return NumberUtil . div ( personalRate - avgNumber , sd ) ;
}
// 业务差异值2 = (问题数 - 平均问题数) / 业务标准差
public double calculateDiff2 ( long personalSiz e, double avgNumber , double sd ) {
// 业务差异值2 = (加权问题数 - 平均问题数) / 业务标准差
public double calculateDiff2 ( double personalScore , double avgNumber , double sd ) {
if ( sd = = 0 ) {
return 0 ;
}
return NumberUtil . div ( personalSize - avgNumber , sd ) ;
log . info ( "业务差异值(数量) = ({} - {}) / {}" , personalScore , avgNumber , sd ) ;
return NumberUtil . div ( personalScore - avgNumber , sd ) ;
}
public double calculateBusinessScore ( double diff , long personalSize ) {
public double calculateBusinessScore ( double diff , double personalSize ) {
if ( personalSize = = 0 ) {
return 0 ;
}
return 50 + ( diff * 15 ) ;
log . info ( "单个业务风险指数 = 50 + ({} * 5)" , diff ) ;
return 50 + ( diff * 5 ) ;
}
private final SupDepartService departService ;
@ -227,49 +213,85 @@ public class NegativeScoreService {
Double totalScore = scorePolices . stream ( ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) ;
List < String > expressionArr = new ArrayList < > ( ) ;
StringBuilder remarks = new StringBuilder ( ) ;
List < Double > scores = new ArrayList < > ( ) ;
List < Double > weights = new ArrayList < > ( ) ;
double policeScore = Arrays . stream ( BusinessTypeEnum . values ( ) ) . mapToDouble ( businessTypeEnum - > {
log . info ( "业务 【{}】 开始-------------------------------------------------------------------" , businessTypeEnum . getLabel ( ) ) ;
List < NegativeScorePolice > businessScorePolice = scorePolices . stream ( ) . filter ( item - > item . getBusinessTypeCode ( ) . equals ( businessTypeEnum . getValue ( ) ) ) . toList ( ) ;
// 业务加权问题总数
double businessWeightScore = businessScorePolice . stream ( ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) ;
log . info ( "业务加权问题数 = {}" , businessWeightScore ) ;
// 业务涉及人数
int policeSize = businessScorePolice . stream ( ) . map ( NegativeScorePolice : : getIdCode ) . collect ( Collectors . toSet ( ) ) . size ( ) ;
remarks . append ( String . format ( "业务设计人数 %s" , policeSize ) ) ;
// 业务问题数
int businessSize = businessScorePolice . size ( ) ;
//---------------------------------------------------------
// 平均问题数
double avgNumber = calculateAvgNumber ( businessSize , policeSize ) ;
// 差值集合 = 个人问题数 - 平均问题数
Map < String , List < NegativeScorePolice > > group = businessScorePolice . stream ( ) . collect ( Collectors . groupingBy ( NegativeScorePolice : : getIdCode ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > val . size ( ) - avgNumber ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd ( diffNumbers , policeSize ) ;
log . info ( "业务标准差为:{}" , sd ) ;
log . info ( "业务涉及人数 = {}" , policeSize ) ;
// 业务加权问题数(风险指数)
double personalScore = businessScorePolice . stream ( ) . filter ( item - > idCode . equals ( item . getIdCode ( ) ) ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) ;
log . info ( "个人业务加权问题数 = {}" , personalScore ) ;
// 业务差异值
double diff ;
long personalSize = businessScorePolice . stream ( ) . filter ( item - > idCode . equals ( item . getIdCode ( ) ) ) . count ( ) ;
if ( businessTypeEnum . getBusinessVolume ( ) ) {
diff = calculateDiff1 ( businessScorePolice , police , beginTime , endTime , businessTypeEnum . getValue ( ) , sd ) ;
if ( false ) {
String departId = depart . getId ( ) ;
// 如果是4级单位 则找他上级单位
if ( depart . getLevel ( ) = = 4 ) {
departId = departService . getById ( depart . getPid ( ) ) . getId ( ) ;
}
List < BusinessDepart > businessDeparts = businessDepartService . list ( beginTime , endTime , departId , businessTypeEnum . getValue ( ) ) ;
// 单位总业务量
int totalBusinessSize = businessDeparts . stream ( ) . mapToInt ( BusinessDepart : : getNumber ) . sum ( ) ;
log . info ( "单位总业务量 = {}" , totalBusinessSize ) ;
// 平均加权问题发生率
double avgNumber = calculateAvgNumber ( businessWeightScore , totalBusinessSize ) ;
log . info ( "平均加权问题发生率 = {}" , avgNumber ) ;
Map < String , List < NegativeScorePolice > > group = businessScorePolice . stream ( ) . collect ( Collectors . groupingBy ( NegativeScorePolice : : getIdCode ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > {
if ( totalBusinessSize = = 0 ) {
return - avgNumber ;
}
return ( val . stream ( ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) / totalBusinessSize ) - avgNumber ;
} ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd1 ( diffNumbers , policeSize ) ;
double rate = personalScore / totalBusinessSize ;
log . info ( "个人问题发生率 = {} / {}" , personalScore , totalBusinessSize ) ;
log . info ( "个人问题发生率 = {}" , rate ) ;
diff = calculateDiff1 ( personalScore / totalBusinessSize , avgNumber , sd ) ;
} else {
diff = calculateDiff2 ( personalSize , avgNumber , sd ) ;
remarks . append ( String . format ( "业务涉及人数 %s" , policeSize ) ) ;
// 业务平均加权问题数
double avgNumber = calculateAvgNumber ( businessWeightScore , policeSize ) ;
// 差值集合 = 个人问题数 - 平均问题数
Map < String , List < NegativeScorePolice > > group = businessScorePolice . stream ( ) . collect ( Collectors . groupingBy ( NegativeScorePolice : : getIdCode ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > val . stream ( ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) - avgNumber ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd2 ( diffNumbers , policeSize ) ;
log . info ( "业务标准差为 = {}" , sd ) ;
diff = calculateDiff2 ( personalScore , avgNumber , sd ) ;
}
log . info ( "业务差异值为:{}" , diff ) ;
log . info ( "业务差异值为 = {}" , diff ) ;
// 业务风险指数
double businessScore = calculateBusinessScore ( diff , personalSize ) ;
log . info ( "业务风险指数:{}" , businessScore ) ;
double businessScore = calculateBusinessScore ( diff , personalScor e ) ;
// 业务权重
Double score = businessScorePolice . stream ( ) . mapToDouble ( NegativeScorePolice : : getScore ) . sum ( ) ;
double businessWeight = calculateBusinessWeight ( totalScore , score ) ;
double businessWeight = calculateBusinessWeight ( score , totalS core) ;
expressionArr . add ( String . format ( "(%s * %s)" , businessScore , businessWeight ) ) ;
remarks . append ( String . format ( "%s:" , businessTypeEnum . getLabel ( ) ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务涉及人数 %s" , policeSize ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务问题数 %s" , businessSize ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "平均问题数 %s" , avgNumber ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务标准差 %s" , sd ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务问题数 %s" , businessWeightScore ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务差异值 %s" , diff ) ) . append ( "\n" ) ;
log . info ( "业务风险指数 = {}" , businessScore ) ;
log . info ( "业务权重 = {}" , businessWeight ) ;
log . info ( "单个业务风险指数 = {} * {}" , businessScore , businessWeight ) ;
log . info ( "单个业务结束-------------------------------------------------------------------" , businessTypeEnum . getLabel ( ) ) ;
scores . add ( NumberUtil . round ( businessScore , 2 ) . doubleValue ( ) ) ;
weights . add ( NumberUtil . round ( businessWeight * 100 , 2 ) . doubleValue ( ) ) ;
return NumberUtil . mul ( businessScore , businessWeight ) ;
} ) . sum ( ) ;
BigDecimal score = NumberUtil . roundHalfEven ( policeScore , 2 ) ;
String expression = String . join ( " + " , expressionArr ) ;
return List . of ( score , expression , remarks ) ;
return List . of ( score , expression , remarks , scores , weights ) ;
}
/ * *
@ -288,35 +310,46 @@ public class NegativeScoreService {
StringBuilder remarks = new StringBuilder ( ) ;
double policeScore = Arrays . stream ( BusinessTypeEnum . values ( ) ) . mapToDouble ( businessTypeEnum - > {
List < NegativeScoreDepart > businessScoreDeparts = scoreDeparts . stream ( ) . filter ( item - > item . getBusinessTypeCode ( ) . equals ( businessTypeEnum . getValue ( ) ) ) . toList ( ) ;
// 业务加权问题数
double businessWeightScore = businessScoreDeparts . stream ( ) . mapToDouble ( NegativeScoreDepart : : getScore ) . sum ( ) ;
// 业务涉及人数
int departSize = businessScoreDeparts . stream ( ) . map ( NegativeScoreDepart : : getDepartId ) . collect ( Collectors . toSet ( ) ) . size ( ) ;
// 当前部门问题数
long personalSize = businessScoreDeparts . stream ( ) . filter ( item - > departId . equals ( item . getDepartId ( ) ) ) . count ( ) ;
// 平均问题数
double avgNumber = calculateAvgNumber ( businessScoreDeparts . size ( ) , departSize ) ;
// 差值集合 = 个人问题数 - 平均问题数
Map < String , List < NegativeScoreDepart > > group = businessScoreDeparts . stream ( ) . collect ( Collectors . groupingBy ( NegativeScoreDepart : : getDepartId ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > val . size ( ) - avgNumber ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd ( diffNumbers , departSize ) ;
// 业务加权问题数(风险指数)
double personalScore = businessScoreDeparts . stream ( ) . filter ( item - > departId . equals ( item . getDepartId ( ) ) ) . mapToDouble ( NegativeScoreDepart : : getScore ) . sum ( ) ;
// 业务差异值
double diff ;
if ( businessTypeEnum . getBusinessVolume ( ) ) {
diff = calculateDiff1ByDepart ( businessScoreDeparts , departId , beginTime , endTime , businessTypeEnum . getValue ( ) , sd ) ;
if ( false ) {
List < BusinessDepart > businessDeparts = businessDepartService . list ( beginTime , endTime , departId , businessTypeEnum . getValue ( ) ) ;
// 总业务量
int totalBusinessSize = businessDeparts . stream ( ) . mapToInt ( BusinessDepart : : getNumber ) . sum ( ) ;
// 平均加权问题发生率
double avgNumber = calculateAvgNumber ( businessWeightScore , totalBusinessSize ) ;
Map < String , List < NegativeScoreDepart > > group = businessScoreDeparts . stream ( ) . collect ( Collectors . groupingBy ( NegativeScoreDepart : : getDepartId ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > val . stream ( ) . mapToDouble ( NegativeScoreDepart : : getScore ) . sum ( ) - avgNumber ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd1 ( diffNumbers , departSize ) ;
log . info ( "" ) ;
diff = calculateDiff1 ( personalScore , avgNumber , sd ) ;
} else {
// 当前部门问题数
long personalSize = businessScoreDeparts . stream ( ) . filter ( item - > departId . equals ( item . getDepartId ( ) ) ) . count ( ) ;
// 平均问题数
double avgNumber = calculateAvgNumber ( businessScoreDeparts . size ( ) , departSize ) ;
// 差值集合 = 个人问题数 - 平均问题数
Map < String , List < NegativeScoreDepart > > group = businessScoreDeparts . stream ( ) . collect ( Collectors . groupingBy ( NegativeScoreDepart : : getDepartId ) ) ;
double [ ] diffNumbers = group . values ( ) . stream ( ) . mapToDouble ( val - > val . size ( ) - avgNumber ) . toArray ( ) ;
// 业务标准差
double sd = calculateSd2 ( diffNumbers , departSize ) ;
diff = calculateDiff2 ( personalSize , avgNumber , sd ) ;
}
// 业务风险指数
double businessScore = calculateBusinessScore ( diff , personalSize ) ;
double businessScore = calculateBusinessScore ( diff , personalScor e ) ;
// 业务权重
Double score = businessScoreDeparts . stream ( ) . mapToDouble ( NegativeScoreDepart : : getScore ) . sum ( ) ;
double businessWeight = calculateBusinessWeight ( totalScore , score ) ;
double businessWeight = calculateBusinessWeight ( score , totalS core) ;
expressionArr . add ( String . format ( "(%s * %s)" , businessScore , businessWeight ) ) ;
remarks . append ( String . format ( "%s:" , businessTypeEnum . getLabel ( ) ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务涉及人数 %s" , departSize ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "当前部门问题数 %s" , personalSize ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "平均问题数 %s" , avgNumber ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务标准差 %s" , sd ) ) . append ( "\n" ) ;
remarks . append ( String . format ( "业务差异值 %s" , diff ) ) . append ( "\n" ) ;
return NumberUtil . mul ( businessScore , businessWeight ) ;
} ) . sum ( ) ;