package com.gkhy.safePlatform.riskCtrl.service.impl; import com.gkhy.safePlatform.account.rpc.apimodel.AccountDepartmentService; import com.gkhy.safePlatform.account.rpc.apimodel.model.enums.DepartmentLevelEnum; import com.gkhy.safePlatform.account.rpc.apimodel.model.resp.DepInfoRPCRespDTO; import com.gkhy.safePlatform.account.rpc.apimodel.model.resp.DepRPCRespDTO; import com.gkhy.safePlatform.commons.enums.ResultCodes; import com.gkhy.safePlatform.commons.vo.ResultVO; import com.gkhy.safePlatform.commons.vo.SearchResultVO; import com.gkhy.safePlatform.doublePrevent.rpc.apimodel.PreventRPCDataCountService; import com.gkhy.safePlatform.emergency.rpc.api.EmergencyRpcAPi; import com.gkhy.safePlatform.incidentManage.rpc.api.IncidentManageRpcAPi; import com.gkhy.safePlatform.riskCtrl.constant.SpiWeighValue; import com.gkhy.safePlatform.riskCtrl.entity.RiskSpiReport; import com.gkhy.safePlatform.riskCtrl.entity.SpiReportDetail; import com.gkhy.safePlatform.riskCtrl.model.bo.EmergencyDataBO; import com.gkhy.safePlatform.riskCtrl.model.bo.IncidentDataBO; import com.gkhy.safePlatform.riskCtrl.model.bo.RiskDataBO; import com.gkhy.safePlatform.riskCtrl.utils.SpiItemAnalysisHandler; import com.gkhy.safePlatform.riskCtrl.model.dto.req.CreateNewRespSpiReportReqDTO; import com.gkhy.safePlatform.riskCtrl.model.dto.req.SearchRiskSpiReportConditionDTO; import com.gkhy.safePlatform.riskCtrl.model.dto.resp.RiskSpiRepostRespDTO; import com.gkhy.safePlatform.riskCtrl.model.dto.resp.SpiReportDetailDTO; import com.gkhy.safePlatform.riskCtrl.model.dto.resp.SpiValueRespDTO; import com.gkhy.safePlatform.riskCtrl.service.RiskSpiService; import com.gkhy.safePlatform.riskCtrl.service.baseService.*; import org.apache.dubbo.config.annotation.DubboReference; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.transaction.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.TimeUnit; @Service public class RiskSpiServiceImpl implements RiskSpiService { @Autowired private RiskSpiReportService riskSpiReportService; @Autowired private SpiReportDetailService spiReportDetailService; @Autowired private RiskMonthReportService riskMonthReportService; @Autowired private PreventMonthReportDetailService preventMonthReportDetailService; @Autowired private IncidentMonthReportItemService incidentMonthReportItemService; @Autowired private EmergencyPracticeReportItemService emergencyPracticeReportItemService; @Autowired private CollectReportDataService collectReportDataService; @DubboReference(check = false) private AccountDepartmentService departmentService; @DubboReference(check = false) private IncidentManageRpcAPi incidentManageRpcAPi; @DubboReference(check = false) private PreventRPCDataCountService preventRPCDataCountService; @DubboReference(check = false) private EmergencyRpcAPi emergencyRpcAPi; @Autowired private RedissonClient redissonClient; @Transactional @Override public ResultVO saveOneRiskSpiReport(CreateNewRespSpiReportReqDTO dto) { ResultVO resultVO = new ResultVO<>(); if(dto == null){ resultVO.setCode(ResultCodes.CLIENT_PARAM_NULL.getCode()); resultVO.setMsg(ResultCodes.CLIENT_PARAM_ERROR.getDesc()); return resultVO; } RiskSpiReport report = new RiskSpiReport(); BeanUtils.copyProperties(dto,report); report.setGmtCreate(LocalDateTime.now()); if(riskSpiReportService.getBaseMapper().insert(report) > 0){ resultVO.setCode(ResultCodes.OK.getCode()); }else { resultVO.setCode(ResultCodes.SERVER_ADD_ERROR.getCode()); resultVO.setMsg(ResultCodes.SERVER_ADD_ERROR.getDesc()); } return resultVO; } @Override public SearchResultVO getOneRiskSpiReportById(Long reportId) { return null; } @Override public SearchResultVO> listRiskSpiReportListByConditions(SearchRiskSpiReportConditionDTO conditionDTO) { SearchResultVO> resultVO = new SearchResultVO<>(); resultVO.setCode(ResultCodes.OK.getCode()); resultVO.setUsePage(false); resultVO.setCount(0); if(conditionDTO == null){ return resultVO; } if(conditionDTO.getYear() != null && conditionDTO.getBeginMonth() != null){ if(conditionDTO.getEndMonth() != null && conditionDTO.getBeginMonth() < conditionDTO.getEndMonth()){ return resultVO; } } List reportList = riskSpiReportService.listByConditions(conditionDTO); if(reportList != null && !reportList.isEmpty()){ List dtoList = new ArrayList<>(); reportList.forEach(r -> { RiskSpiRepostRespDTO dto = new RiskSpiRepostRespDTO(); BeanUtils.copyProperties(r,dto); dtoList.add(dto); }); } return resultVO; } /** * 查找部门月度SPI报表 * @param depId * @param year * @param month * @return */ @Override public SearchResultVO getMonthlySpiReport(Long depId, Integer year, Integer month) { SearchResultVO searchResultVO = new SearchResultVO<>(); searchResultVO.setCode(ResultCodes.OK.getCode()); searchResultVO.setCount(0); searchResultVO.setUsePage(false); RiskSpiReport spiReport = riskSpiReportService.getMonthlySpiReport(depId,year,month); if(spiReport != null && spiReport.getDepId().equals(depId)){ searchResultVO.setCount(1); RiskSpiRepostRespDTO dto = new RiskSpiRepostRespDTO(); BeanUtils.copyProperties(spiReport,dto); searchResultVO.setData(dto); } return searchResultVO; } /** * 生成部门级SPI月报 * @param depId * @param year * @param month * @return */ @Override public ResultVO generateDepartmentSpiMonthReport(Long depId, Integer year, Integer month) { ResultVO resultVO = new ResultVO<>(); if(depId == null || depId < 0 || year == null || month == null){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("参数错误"); return resultVO; } //1、判断年份月份是否合理 LocalDateTime nowTime = LocalDateTime.now(); if(year > nowTime.getYear() || year < 2022){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("年份错误"); return resultVO; }else if(year.equals(nowTime.getYear()) && month >= nowTime.getMonthValue()){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("月份错误"); return resultVO; } //必须至少提前21天 if(nowTime.getDayOfMonth() < 21){ LocalDate td = LocalDate.of(year,month,21); if(td.plusMonths(1L).isAfter(nowTime.toLocalDate())){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("未到生成月报时间"); return resultVO; } } //2、判断部门是否存在 ResultVO depInfoRpcResult = departmentService.getDepInfoByDepId(depId); if(!depInfoRpcResult.getCode().equals(ResultCodes.OK.getCode())){ resultVO.setCode(ResultCodes.SERVER_ERROR); return resultVO; } DepInfoRPCRespDTO depInfo = (DepInfoRPCRespDTO) depInfoRpcResult.getData(); if(depInfo == null){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("部门不存在"); return resultVO; } //加分布式锁 String lockName = "LOCK_RISKCTRL_SPI_REPORT_"+depId; RLock lock = redissonClient.getLock(lockName); //最长加锁时间30秒 lock.lock(30, TimeUnit.SECONDS); //看是否已经生成该部门指定年月的SPI报表 SearchResultVO riskSpiSearchResult = getMonthlySpiReport(depId,year, month); if(riskSpiSearchResult.getCode().equals(ResultCodes.OK.getCode()) && riskSpiSearchResult.getCount() > 0){ //该部门已经生成了指定年月的SPI报表 lock.unlock(); //释放锁 resultVO.setCode(ResultCodes.BUSINESS_ERROR.getCode()); resultVO.setMsg("SPI月报已经生成"); return resultVO; } //计算SPI ResultVO calSpiResultVO = calSpiValue(depId,year, month); if(calSpiResultVO.getCode().equals(ResultCodes.OK.getCode())){ SpiValueRespDTO spiValueRespDTO = (SpiValueRespDTO) calSpiResultVO.getData(); if(spiValueRespDTO != null && depId.longValue() == spiValueRespDTO.getDepId().longValue()){ //生成月报入库 RiskSpiReport riskSpiReport = new RiskSpiReport(); riskSpiReport.setDepId(depId); riskSpiReport.setYear(year); riskSpiReport.setMonth(month); riskSpiReport.setVal(spiValueRespDTO.getSpiVal()); riskSpiReport.setGmtCreate(LocalDateTime.now()); if(riskSpiReportService.save(riskSpiReport) == true){ resultVO.setCode(ResultCodes.OK.getCode()); lock.unlock(); }else { lock.unlock(); throw new RuntimeException("数据库保存SPI月度报表出错"); } } }else { lock.unlock(); } return resultVO; } /** * 定时调度生成部门SPI月度报表 * @param depId * @return */ @Transactional @Override public ResultVO generateDepartmentSpiReportMonthlyScheduled(Long depId) { ResultVO resultVO = new ResultVO<>(); if(depId == null || depId < 0){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("参数错误"); } LocalDate nowDate = LocalDate.now(); //当前日期已经过了21号,可以生成上个月的固化报表 if(nowDate.getDayOfMonth() > 15){ LocalDate targetTime = nowDate.minusMonths(1L); resultVO = generateDepartmentSpiMonthReport(depId, targetTime.getYear(), targetTime.getMonthValue()); }else { resultVO.setCode(ResultCodes.BUSINESS_ERROR.getCode()); resultVO.setCode("不在生成日报的时间"); } return resultVO; } /** * 定时调度生成企业SPI月度报表 * @param eid * @return */ @Transactional @Override public ResultVO generateCompanySpiReportMonthlyScheduled(Long eid) { ResultVO generateResultVO = new ResultVO<>(); ResultVO> resultVO = departmentService.depList(); if(!resultVO.getCode().equals(ResultCodes.OK.getCode())){ generateResultVO.setCode(ResultCodes.BUSINESS_ERROR.getCode()); generateResultVO.setMsg("RPC获取部门数据出错"); return generateResultVO; } List depList = (List) resultVO.getData(); if(depList == null || depList.isEmpty()){ generateResultVO.setCode(ResultCodes.BUSINESS_ERROR.getCode()); generateResultVO.setMsg("未获取到部门数据"); } depList.forEach(dep -> { if(dep.getDepLevel().equals(DepartmentLevelEnum.COMPANY.code)){ //公司 }else if(dep.getDepLevel().equals(DepartmentLevelEnum.BUSINESS.code)){ //事业部 } else if(dep.getDepLevel().equals(DepartmentLevelEnum.WORKSHOP.code)){ //车间 } }); //todo : 完善公司级月报 return generateResultVO; } @Transactional @Override public ResultVO calSpiValue(Long depId, Integer year, Integer month) { ResultVO resultVO = new ResultVO<>(); if(year == null || year < 0 || year > 9999){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg(ResultCodes.CLIENT_PARAM_ERROR.getDesc()); return resultVO; } if(month != null && (month < 0 || month > 12)){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg(ResultCodes.CLIENT_PARAM_ERROR.getDesc()); return resultVO; } ResultVO depInfoRpcResult = departmentService.getDepInfoByDepId(depId); if(!depInfoRpcResult.getCode().equals(ResultCodes.OK.getCode())){ throw new RuntimeException("RPC调用出错"); } DepInfoRPCRespDTO depInfo = (DepInfoRPCRespDTO) depInfoRpcResult.getData(); if(depInfo == null){ throw new RuntimeException("部门不存在"); } //1、获取双重预防隐患统计数据 RiskDataBO riskDataBO = collectReportDataService.getPreventRiskData(depInfo,year,month); //2、获取事故管理统计数据 IncidentDataBO incidentDataBO = collectReportDataService.getIncidentCountData(depInfo,year,month); //3、获取应急演练次数统计数据 EmergencyDataBO emergencyDataBO = collectReportDataService.getEmergencyCountData(depInfo,year,month); SpiItemAnalysisHandler spiItemAnalysisHandler = new SpiItemAnalysisHandler(); //4.1计算I1 BigDecimal i1 = BigDecimal.valueOf(0); if(riskDataBO != null){ i1 = spiItemAnalysisHandler.calI1(riskDataBO); } //4.2计算I2 BigDecimal i2 = BigDecimal.valueOf(0); if(riskDataBO != null){ i2 = spiItemAnalysisHandler.calI2(riskDataBO); } //4.3计算I3 BigDecimal i3 = BigDecimal.valueOf(0); if(riskDataBO != null){ i3 = spiItemAnalysisHandler.calI3(riskDataBO); } //4.4计算I6 BigDecimal i6 = BigDecimal.valueOf(0); if(emergencyDataBO != null){ i6 = spiItemAnalysisHandler.calI6(emergencyDataBO); } //4.5计算I7 BigDecimal i7 = BigDecimal.valueOf(0); if(emergencyDataBO != null){ i7 = spiItemAnalysisHandler.calI7(emergencyDataBO,true,year, month); } //4.6计算I8 BigDecimal i8 = BigDecimal.valueOf(0); if(incidentDataBO != null){ i8 = spiItemAnalysisHandler.calI8Val(incidentDataBO); } //4.7计算I9 BigDecimal i9 = BigDecimal.valueOf(0); if(incidentDataBO != null){ i9 = spiItemAnalysisHandler.calI9Val(incidentDataBO); } //5、计算SPI BigDecimal spiVal = i1.multiply(SpiWeighValue.W1) .add(i2.multiply(SpiWeighValue.W2)) .add(i3.multiply(SpiWeighValue.W3)) .add(i6.multiply(SpiWeighValue.W6)) .add(i7.multiply(SpiWeighValue.W7)) .add(i8.multiply(SpiWeighValue.W8)) .add(i9.multiply(SpiWeighValue.W9)); SpiValueRespDTO spiValueRespDTO = new SpiValueRespDTO(); spiValueRespDTO.setDepId(depId); spiValueRespDTO.setDepLevel(depInfo.getDepLevel()); spiValueRespDTO.setDepName(depInfo.getDepName()); spiValueRespDTO.setYear(year); spiValueRespDTO.setMonth(month); spiValueRespDTO.setSpiVal(spiVal.setScale(2, RoundingMode.HALF_UP)); resultVO.setCode(ResultCodes.OK.getCode()); resultVO.setData(spiValueRespDTO); return resultVO; } /** * 计算最近12个月的SPI值 * @param depId * @return */ @Override public ResultVO> calSpiValueForLast12Months(Long depId) { ResultVO> resultVO = new ResultVO<>(); resultVO.setCode(ResultCodes.OK.getCode()); List list = new ArrayList<>(); //获取最近的12个月 LocalDateTime nowTime = LocalDateTime.now(); for(long i=11;i>=0;i--){ LocalDateTime targetTime = nowTime.minusMonths(i); // ResultVO r = calSpiValue(depId, targetTime.getYear(), targetTime.getMonthValue()); ResultVO r = getSpiReportByMonth(depId, targetTime.getYear(),targetTime.getMonthValue()); if(r.getCode().equals(ResultCodes.OK.getCode()) && r.getData() != null){ list.add((SpiValueRespDTO) r.getData()); } } resultVO.setData(list); return resultVO; } /** * 获取任意部门指定年月份的SPI报表 * @param depId * @param year * @param month * @return */ @Override public ResultVO getSpiReportByMonth(Long depId, Integer year, Integer month) { ResultVO resultVO = new ResultVO<>(); if(depId == null || depId < 0 || year == null || month == null){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("参数错误"); return resultVO; } //1、判断年份月份是否合理 LocalDateTime nowTime = LocalDateTime.now(); if(year > nowTime.getYear() || year < 2022){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("年份错误"); return resultVO; }else if(year.equals(nowTime.getYear()) && month > nowTime.getMonthValue()){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("月份错误"); return resultVO; } //2、判断部门是否存在 ResultVO depInfoRpcResult = departmentService.getDepInfoByDepId(depId); if(!depInfoRpcResult.getCode().equals(ResultCodes.OK.getCode())){ resultVO.setCode(ResultCodes.SERVER_ERROR); return resultVO; } DepInfoRPCRespDTO depInfo = (DepInfoRPCRespDTO) depInfoRpcResult.getData(); if(depInfo == null){ resultVO.setCode(ResultCodes.CLIENT_PARAM_ERROR.getCode()); resultVO.setMsg("部门不存在"); return resultVO; } //3、查找该月份是否有固化报表,有就返回报表信息,没有就生成该月的固化报表,并返回报表信息 RiskSpiReport riskSpiReport = riskSpiReportService.getMonthlySpiReport(depId,year,month); if(riskSpiReport == null || riskSpiReport.getDepId() == null){ //不存在固化报表,要先生成 ResultVO genReportResult = generateDepartmentSpiMonthReport(depId,year,month); if(genReportResult.getCode().equals(ResultCodes.OK.getCode())){ //生成月报成功 //重新从数据库获取数据 riskSpiReport = riskSpiReportService.getMonthlySpiReport(depId,year,month); if(riskSpiReport != null){ //打包数据 SpiValueRespDTO spiValueRespDTO = packageSpiDto(riskSpiReport); spiValueRespDTO.setDepName(depInfo.getDepName()); spiValueRespDTO.setDepLevel(depInfo.getDepLevel()); resultVO.setData(spiValueRespDTO); } }else { //没有成功生成月报 //实时计算SPI ResultVO calRes = calSpiValue(depId,year,month); if(calRes.getCode().equals(ResultCodes.OK.getCode()) && calRes.getData() != null){ SpiValueRespDTO spiValueRespDTO = (SpiValueRespDTO) calRes.getData(); resultVO.setData(spiValueRespDTO); } } }else { //存在该月的固化报表,可直接用 //打包数据 SpiValueRespDTO spiValueRespDTO = packageSpiDto(riskSpiReport); spiValueRespDTO.setDepName(depInfo.getDepName()); spiValueRespDTO.setDepLevel(depInfo.getDepLevel()); resultVO.setData(spiValueRespDTO); } resultVO.setCode(ResultCodes.OK.getCode()); return resultVO; } /** * 新增一个部门的SPI详细月报记录 * @param depId * @param year * @param month * @return */ @Override public ResultVO addOneSpiReportDetail(Long depId, Integer year, Integer month) { return null; } /** * 获取指定部门指定年月的SPI详细报表 * @param eid * @param depId * @param year * @param month * @return */ @Override public SearchResultVO findSpiReportDetailForOne(Long eid, Long depId, Integer year, Integer month) { SearchResultVO resultVO = new SearchResultVO<>(); resultVO.setUsePage(false); resultVO.setCode(ResultCodes.OK.getCode()); if(depId == null || depId < 0 || year == null || month == null){ resultVO.setMsg(ResultCodes.CLIENT_PARAM_NULL.getDesc()); return resultVO; } if(year < 2000 || year > 9999 || month < 0 || month > 12){ resultVO.setMsg(ResultCodes.CLIENT_PARAM_ERROR.getDesc()); return resultVO; } SpiReportDetail detail = spiReportDetailService.findOneByMonth(eid,depId,year,month); if(detail != null){ SpiReportDetailDTO detailDTO = new SpiReportDetailDTO(); BeanUtils.copyProperties(detail,detailDTO); resultVO.setCount(1); resultVO.setData(detailDTO); } return resultVO; } /** * 获取指定部门指定日期区间内的SPI报表列表 * @param eid * @param depId * @param startYear * @param startMonth * @param endYear * @param endMonth * @return */ @Override public SearchResultVO> listSpiReportDetailByCondition(Long eid, Long depId, Integer startYear, Integer startMonth,Integer endYear, Integer endMonth) { SearchResultVO> resultVO = new SearchResultVO<>(); resultVO.setCode(ResultCodes.OK.getCode()); resultVO.setUsePage(false); if(depId == null || depId < 0 || startYear == null || startMonth == null || endYear == null || endMonth == null){ resultVO.setMsg(ResultCodes.CLIENT_PARAM_NULL.getDesc()); return resultVO; } if(startYear < 2000 || startYear > 9999 || startMonth < 1 || startMonth > 12){ resultVO.setMsg(ResultCodes.CLIENT_PARAM_ERROR.getDesc()); return resultVO; } LocalDate countBeginDate = LocalDate.of(startYear,startMonth,1); LocalDate countEndDate = LocalDate.of(endYear,endMonth,1); List detailList = spiReportDetailService.listByConditions(eid,depId,countBeginDate, countEndDate); if(detailList != null && !detailList.isEmpty()){ List detailDTOList = new ArrayList<>(); for(SpiReportDetail detail : detailList){ if(detail != null){ SpiReportDetailDTO detailDTO = new SpiReportDetailDTO(); BeanUtils.copyProperties(detail,detailDTO); detailDTOList.add(detailDTO); } } resultVO.setData(detailDTOList); resultVO.setCount(detailDTOList.size()); } return resultVO; } /** * 将数据库取出的SPI月报对象重新包装成接口需要的DTO * @param riskSpiReport * @return */ private SpiValueRespDTO packageSpiDto(RiskSpiReport riskSpiReport){ if(riskSpiReport == null || riskSpiReport.getDepId() == null ){ return null; } SpiValueRespDTO spiValueRespDTO = new SpiValueRespDTO(); spiValueRespDTO.setDepId(riskSpiReport.getDepId()); spiValueRespDTO.setYear(riskSpiReport.getYear()); spiValueRespDTO.setMonth(riskSpiReport.getMonth()); spiValueRespDTO.setSpiVal(riskSpiReport.getVal()); return spiValueRespDTO; } }